GP-6576 Corrected Structure insertAtOffset bug

This commit is contained in:
ghidra1
2026-03-17 15:15:21 -04:00
parent 842e057244
commit 692571ec29
4 changed files with 236 additions and 8 deletions

View File

@@ -540,6 +540,40 @@ public class StructureDataTypeTest extends AbstractGenericTest {
"Length: 13 Alignment: 1\n", struct.toString());
}
@Test
public void testInsertWithZeroArrayAtOffset3() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.insertAtOffset(2, zeroArray, -1, "z4", null);
struct.insertAtOffset(0, zeroArray, -1, "z1", null);
struct.insertAtOffset(0, zeroArray, -1, "z2", null);
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
struct.insertAtOffset(0, zeroArray, -1, "z3", null);
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 float[0] 0 z3 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
}
@Test
public void testInsertAtOffsetPastEnd() {
struct.insertAtOffset(100, new FloatDataType(), 4);
@@ -861,6 +895,44 @@ public class StructureDataTypeTest extends AbstractGenericTest {
//@formatter:on
}
@Test
public void testInsertZeroLengthBitfieldAtOffset() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.insertAtOffset(0, zeroArray, -1, "z1", null);
struct.insertAtOffset(0, zeroArray, -1, "z2", null);
struct.insertAtOffset(2, zeroArray, -1, "z4", null);
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
try {
struct.insertBitFieldAt(0, 1, 0, CharDataType.dataType, 0, null, null);
}
catch (InvalidDataTypeException e) {
failWithException("Unexpected", e);
}
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 char:0(0) 0 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
}
@Test
public void testInsertBitFieldAtBigEndian() throws Exception {
@@ -2053,6 +2125,39 @@ public class StructureDataTypeTest extends AbstractGenericTest {
assertTrue(ByteDataType.dataType.isEquivalent(comps[4].getDataType()));
}
@Test
public void testReplaceAtWithZeroLength1() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.replaceAtOffset(0, zeroArray, -1, "z1", null);
struct.replaceAtOffset(0, zeroArray, -1, "z2", null);
struct.replaceAtOffset(2, zeroArray, -1, "z4", null);
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
struct.replaceAtOffset(0, zeroArray, -1, "z3", null);
assertEquals("/TestStruct\n" +
"pack(disabled)\n" +
"Structure TestStruct {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 float[0] 0 z3 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
}
@Test
public void testSetName() throws Exception {
Structure s1 = new StructureDataType("Test1", 0);

View File

@@ -1337,6 +1337,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
dataType = resolve(dataType);
DataTypeUtilities.checkAncestry(this, dataType);
length = getPreferredComponentLength(dataType, length);
if ((offset > structLength) && !isPackingEnabled()) {
numComponents += offset - structLength;
structLength = offset;
@@ -1352,7 +1354,8 @@ class StructureDB extends CompositeDB implements StructureInternal {
if (index >= 0) {
index = backupToFirstComponentContainingOffset(index, offset);
index = afterNonZeroComponentsAtOffset(index, offset);
if (index < components.size()) {
if (length != 0 && index < components.size()) {
// NOTE: zero-length component insert does not trigger offset shift
DataTypeComponentDB dtc = components.get(index);
additionalShift = offset - dtc.getOffset();
}
@@ -1364,7 +1367,13 @@ class StructureDB extends CompositeDB implements StructureInternal {
int ordinal = offset;
if (index > 0) {
DataTypeComponentDB dtc = components.get(index - 1);
ordinal = dtc.getOrdinal() + offset - dtc.getEndOffset();
ordinal = dtc.getOrdinal();
if (dtc.getOffset() == offset) {
ordinal += 1;
}
else {
ordinal += offset - dtc.getEndOffset(); // account for undefined components
}
}
if (dataType == DataType.DEFAULT) {
@@ -1375,8 +1384,6 @@ class StructureDB extends CompositeDB implements StructureInternal {
return new DataTypeComponentDB(dataMgr, this, ordinal, offset);
}
length = getPreferredComponentLength(dataType, length);
DBRecord rec = componentAdapter.createRecord(dataMgr.getResolvedID(dataType), key,
length, ordinal, offset, name, comment);
dataType.addParent(this);

View File

@@ -520,6 +520,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
dataType = dataType.clone(dataMgr);
DataTypeUtilities.checkAncestry(this, dataType);
length = getPreferredComponentLength(dataType, length);
if ((offset > structLength) && !isPackingEnabled()) {
numComponents += offset - structLength;
structLength = offset;
@@ -535,7 +537,8 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
if (index >= 0) {
index = backupToFirstComponentContainingOffset(index, offset);
index = afterNonZeroComponentsAtOffset(index, offset);
if (index < components.size()) {
if (length != 0 && index < components.size()) {
// NOTE: zero-length component insert does not trigger offset shift
DataTypeComponentImpl dtc = components.get(index);
additionalShift = offset - dtc.getOffset();
}
@@ -547,7 +550,13 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
int ordinal = offset;
if (index > 0) {
DataTypeComponent dtc = components.get(index - 1);
ordinal = dtc.getOrdinal() + offset - dtc.getEndOffset();
ordinal = dtc.getOrdinal();
if (dtc.getOffset() == offset) {
ordinal += 1;
}
else {
ordinal += offset - dtc.getEndOffset(); // account for undefined components
}
}
if (dataType == DataType.DEFAULT) {
@@ -556,8 +565,6 @@ public class StructureDataType extends CompositeDataTypeImpl implements Structur
return new DataTypeComponentImpl(DataType.DEFAULT, this, 1, ordinal, offset);
}
length = getPreferredComponentLength(dataType, length);
DataTypeComponentImpl dtc = new DataTypeComponentImpl(dataType, this, length, ordinal,
offset, componentName, comment);
dataType.addParent(this);

View File

@@ -567,6 +567,42 @@ public class StructureDBTest extends AbstractGenericTest {
"Length: 13 Alignment: 1\n", struct.toString());
}
@Test
public void testInsertWithZeroArrayAtOffset3() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.insertAtOffset(2, zeroArray, -1, "z4", null);
struct.insertAtOffset(0, zeroArray, -1, "z1", null);
struct.insertAtOffset(0, zeroArray, -1, "z2", null);
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n" +
"", struct.toString());
struct.insertAtOffset(0, zeroArray, -1, "z3", null);
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 float[0] 0 z3 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n" +
"", struct.toString());
}
@Test
public void testInsertAtOffsetPastEnd() {
struct.insertAtOffset(100, new FloatDataType(), 4);
@@ -1017,6 +1053,44 @@ public class StructureDBTest extends AbstractGenericTest {
//@formatter:on
}
@Test
public void testInsertZeroLengthBitfieldAtOffset() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.insertAtOffset(0, zeroArray, -1, "z1", null);
struct.insertAtOffset(0, zeroArray, -1, "z2", null);
struct.insertAtOffset(2, zeroArray, -1, "z4", null);
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
try {
struct.insertBitFieldAt(0, 1, 0, CharDataType.dataType, 0, null, null);
}
catch (InvalidDataTypeException e) {
failWithException("Unexpected", e);
}
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 char:0(0) 0 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n", struct.toString());
}
@Test
public void testInsertBitFieldAtBigEndian() throws Exception {
@@ -2488,6 +2562,41 @@ public class StructureDBTest extends AbstractGenericTest {
assertTrue(ByteDataType.dataType.isEquivalent(comps[4].getDataType()));
}
@Test
public void testReplaceAtWithZeroLength1() {
Array zeroArray = new ArrayDataType(FloatDataType.dataType, 0, -1);
// Clear structure and set length to 8 with only zero-length components
struct.setLength(0);
struct.setLength(8);
struct.replaceAtOffset(0, zeroArray, -1, "z1", null);
struct.replaceAtOffset(0, zeroArray, -1, "z2", null);
struct.replaceAtOffset(2, zeroArray, -1, "z4", null);
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n" +
"", struct.toString());
struct.replaceAtOffset(0, zeroArray, -1, "z3", null);
assertEquals("/Test\n" +
"pack(disabled)\n" +
"Structure Test {\n" +
" 0 float[0] 0 z1 \"\"\n" +
" 0 float[0] 0 z2 \"\"\n" +
" 0 float[0] 0 z3 \"\"\n" +
" 2 float[0] 0 z4 \"\"\n" +
"}\n" +
"Length: 8 Alignment: 1\n" +
"", struct.toString());
}
@Test
public void testSetName() throws Exception {
Structure s1 = new StructureDataType("Test1", 0);