mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 10:49:34 +02:00
GP-4751 Corrected typedef duplicate name resolve
This commit is contained in:
parent
0e2588ba64
commit
7bc04436f2
3 changed files with 122 additions and 11 deletions
|
@ -36,10 +36,6 @@ public class CParserTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method just tries to parse a bunch o'
|
|
||||||
* data types just checking for stack traces.
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
CParser parser = new CParser();
|
CParser parser = new CParser();
|
||||||
|
@ -68,10 +64,6 @@ public class CParserTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
assertEquals(comp.getDataType().getName(),"char");
|
assertEquals(comp.getDataType().getName(),"char");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method just tries to parse a bunch o'
|
|
||||||
* data types just checking for stack traces.
|
|
||||||
*/
|
|
||||||
@Test
|
@Test
|
||||||
public void testLongLong() throws Exception {
|
public void testLongLong() throws Exception {
|
||||||
CParser parser;
|
CParser parser;
|
||||||
|
@ -96,6 +88,27 @@ public class CParserTest extends AbstractGhidraHeadlessIntegrationTest {
|
||||||
assertEquals(8, pdt32.getLength());
|
assertEquals(8, pdt32.getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTypedef() throws Exception {
|
||||||
|
CParser parser;
|
||||||
|
|
||||||
|
parser = new CParser();
|
||||||
|
DataType tdDt = parser.parse("typedef struct foo * foo;");
|
||||||
|
|
||||||
|
assertTrue(tdDt != null);
|
||||||
|
assertTrue(tdDt instanceof TypeDef);
|
||||||
|
System.out.println(tdDt.getPathName());
|
||||||
|
System.out.println(((TypeDef)tdDt).getDataType().getPathName());
|
||||||
|
assertEquals("foo", tdDt.getName());
|
||||||
|
assertEquals("foo.conflict *", ((TypeDef)tdDt).getDataType().getName());
|
||||||
|
assertEquals(4, tdDt.getLength());
|
||||||
|
|
||||||
|
DataType dt = parser.getDataTypeManager().getDataType("/foo");
|
||||||
|
assertTrue(dt != null);
|
||||||
|
assertTrue(dt instanceof TypeDef);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWcharT() throws Exception {
|
public void testWcharT() throws Exception {
|
||||||
|
|
||||||
|
|
|
@ -1445,6 +1445,8 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||||
* <br>
|
* <br>
|
||||||
* NOTE: The original datatype name will be returned unchanged for pointers and arrays since
|
* NOTE: The original datatype name will be returned unchanged for pointers and arrays since
|
||||||
* they cannot be renamed.
|
* they cannot be renamed.
|
||||||
|
* <br>
|
||||||
|
* NOTE: Otherwise, if category does not exist the non-conflict name will be returned.
|
||||||
*
|
*
|
||||||
* @param path the category path of the category where the new data type live in
|
* @param path the category path of the category where the new data type live in
|
||||||
* the data type manager.
|
* the data type manager.
|
||||||
|
@ -1452,16 +1454,39 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||||
* @return the unused conflict name
|
* @return the unused conflict name
|
||||||
*/
|
*/
|
||||||
public String getUnusedConflictName(CategoryPath path, DataType dt) {
|
public String getUnusedConflictName(CategoryPath path, DataType dt) {
|
||||||
String name = dt.getName();
|
|
||||||
if ((dt instanceof Array) || (dt instanceof Pointer) || (dt instanceof BuiltInDataType)) {
|
if ((dt instanceof Array) || (dt instanceof Pointer) || (dt instanceof BuiltInDataType)) {
|
||||||
// name not used - anything will do
|
// name not used - anything will do
|
||||||
return name;
|
return dt.getName();
|
||||||
}
|
}
|
||||||
|
return getUnusedConflictName(getCategory(path), dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets a ".conflict" name that is not currently used by any data
|
||||||
|
* types in the indicated category within this data type manager. If the baseName without
|
||||||
|
* conflict suffix is not used that name will be returned.
|
||||||
|
* <br>
|
||||||
|
* NOTE: The original datatype name will be returned unchanged for pointers and arrays since
|
||||||
|
* they cannot be renamed.
|
||||||
|
* <br>
|
||||||
|
* NOTE: Otherwise, if category does not exist the non-conflict name will be returned.
|
||||||
|
*
|
||||||
|
* @param cat the existing category to check.
|
||||||
|
* @param dt datatype who name is used to establish non-conflict base name
|
||||||
|
* @return the unused conflict name
|
||||||
|
*/
|
||||||
|
private String getUnusedConflictName(Category cat, DataType dt) {
|
||||||
|
if ((dt instanceof Array) || (dt instanceof Pointer) || (dt instanceof BuiltInDataType)) {
|
||||||
|
// name not used - anything will do
|
||||||
|
return dt.getName();
|
||||||
|
}
|
||||||
String baseName = DataTypeUtilities.getNameWithoutConflict(dt);
|
String baseName = DataTypeUtilities.getNameWithoutConflict(dt);
|
||||||
|
if (cat == null) {
|
||||||
|
return baseName;
|
||||||
|
}
|
||||||
String testName = baseName;
|
String testName = baseName;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (getDataType(path, testName) != null) {
|
while (cat.getDataType(testName) != null) {
|
||||||
testName = baseName + DataType.CONFLICT_SUFFIX;
|
testName = baseName + DataType.CONFLICT_SUFFIX;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
testName += Integer.toString(count);
|
testName += Integer.toString(count);
|
||||||
|
@ -3116,6 +3141,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
|
||||||
flags = (short) TypedefDBAdapter.TYPEDEF_FLAG_AUTONAME;
|
flags = (short) TypedefDBAdapter.TYPEDEF_FLAG_AUTONAME;
|
||||||
cat = getCategory(dataType.getCategoryPath()); // force category
|
cat = getCategory(dataType.getCategoryPath()); // force category
|
||||||
}
|
}
|
||||||
|
else if (cat.getDataType(name) != null) {
|
||||||
|
// force use of conflict name if needed
|
||||||
|
name = getUnusedConflictName(cat, typedef);
|
||||||
|
}
|
||||||
DBRecord record = typedefAdapter.createRecord(getID(dataType), name, flags, cat.getID(),
|
DBRecord record = typedefAdapter.createRecord(getID(dataType), name, flags, cat.getID(),
|
||||||
sourceArchiveIdValue, universalIdValue, typedef.getLastChangeTime());
|
sourceArchiveIdValue, universalIdValue, typedef.getLastChangeTime());
|
||||||
TypedefDB typedefDB = new TypedefDB(this, dtCache, typedefAdapter, record);
|
TypedefDB typedefDB = new TypedefDB(this, dtCache, typedefAdapter, record);
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.program.database.data;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import generic.test.AbstractGenericTest;
|
||||||
|
import ghidra.program.model.data.*;
|
||||||
|
|
||||||
|
public class TypedefDBTest extends AbstractGenericTest {
|
||||||
|
|
||||||
|
private final String NAME = "Test";
|
||||||
|
|
||||||
|
private DataTypeManagerDB dataMgr;
|
||||||
|
private int txId;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
dataMgr = new StandAloneDataTypeManager("dummyDTM");
|
||||||
|
txId = dataMgr.startTransaction("Test");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
if (txId > 0) {
|
||||||
|
dataMgr.endTransaction(txId, true);
|
||||||
|
dataMgr.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateNameResolve() throws Exception {
|
||||||
|
|
||||||
|
Structure struct = new StructureDataType(NAME, 0);
|
||||||
|
struct.add(new ByteDataType(), "field1", "Comment1");
|
||||||
|
struct.add(new WordDataType(), null, "Comment2");
|
||||||
|
struct.add(new DWordDataType(), "field3", null);
|
||||||
|
struct.add(new ByteDataType(), "field4", "Comment4");
|
||||||
|
|
||||||
|
Pointer structPtr = new PointerDataType(struct);
|
||||||
|
|
||||||
|
TypeDef typeDef = new TypedefDataType(NAME, structPtr);
|
||||||
|
|
||||||
|
TypeDef td = (TypeDef) dataMgr.resolve(typeDef, null);
|
||||||
|
assertNotNull(td);
|
||||||
|
assertEquals(NAME + ".conflict", td.getName());
|
||||||
|
|
||||||
|
assertTrue(td.isEquivalent(typeDef));
|
||||||
|
|
||||||
|
assertEquals("typedef Test.conflict Test *", td.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue