GT-3530 corrected some regression issues with char formatting

This commit is contained in:
ghidra1 2020-02-06 18:35:17 -05:00
parent 0f335d0250
commit d1d5f9ea16
6 changed files with 53 additions and 36 deletions

View file

@ -48,8 +48,6 @@ public class ConvertToCharAction extends AbstractConvertAction {
@Override @Override
protected String convertToString(Program program, Scalar scalar, boolean isData) { protected String convertToString(Program program, Scalar scalar, boolean isData) {
byte[] bytes = scalar.byteArrayValue(); byte[] bytes = scalar.byteArrayValue();
return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null);
return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null,
program.getMemory().isBigEndian());
} }
} }

View file

@ -818,7 +818,7 @@ public class DataAction4Test extends AbstractDataActionTest {
d = getContextData(); d = getContextData();
assertEquals("ChooseFontW\0\u0015\0ReplaceTextW\0\0\u0004", d.getValue()); assertEquals("ChooseFontW\0\u0015\0ReplaceTextW\0\0\u0004", d.getValue());
assertEquals("\"ChooseFontW\\0\",15,\"\\0ReplaceTextW\\0\\0\",04", assertEquals("\"ChooseFontW\\0\",15h,\"\\0ReplaceTextW\\0\\0\",04h",
d.getDefaultValueRepresentation()); d.getDefaultValueRepresentation());
} }
@ -851,7 +851,7 @@ public class DataAction4Test extends AbstractDataActionTest {
assertEquals("\"ChooseFontW\"", d.getDefaultValueRepresentation()); assertEquals("\"ChooseFontW\"", d.getDefaultValueRepresentation());
d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a0e, 2); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a0e, 2);
assertEquals("15", d.getDefaultValueRepresentation()); assertEquals("15h", d.getDefaultValueRepresentation());
d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a10, 13); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a10, 13);
assertEquals("ReplaceTextW", d.getValue()); assertEquals("ReplaceTextW", d.getValue());
@ -862,7 +862,7 @@ public class DataAction4Test extends AbstractDataActionTest {
assertEquals("\"\"", d.getDefaultValueRepresentation()); assertEquals("\"\"", d.getDefaultValueRepresentation());
d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a1e, 2); d = checkNextData(dit, TerminatedStringDataType.class, 0x01006a1e, 2);
assertEquals("04", d.getDefaultValueRepresentation()); assertEquals("04h", d.getDefaultValueRepresentation());
} }
@Test @Test
@ -890,7 +890,7 @@ public class DataAction4Test extends AbstractDataActionTest {
checkOnDefined(null, UnicodeDataType.class); checkOnDefined(null, UnicodeDataType.class);
d = getContextData(); d = getContextData();
assertEquals("01,00,\"\\0Sample\"", d.getDefaultValueRepresentation()); assertEquals("01h,00h,\"\\0Sample\"", d.getDefaultValueRepresentation());
assertEquals("\1\0Sample", d.getValue()); assertEquals("\1\0Sample", d.getValue());
} }
@ -925,7 +925,7 @@ public class DataAction4Test extends AbstractDataActionTest {
// check for wchar16[2] garbage string // check for wchar16[2] garbage string
d = checkNextData(dit, TerminatedUnicodeDataType.class, 0x01008014, 4); d = checkNextData(dit, TerminatedUnicodeDataType.class, 0x01008014, 4);
assertEquals(d.getLength(), 4); assertEquals(d.getLength(), 4);
assertEquals("01,00", d.getDefaultValueRepresentation()); assertEquals("01h,00h", d.getDefaultValueRepresentation());
assertEquals("\1", d.getValue()); assertEquals("\1", d.getValue());
// check for "Sample" string // check for "Sample" string

View file

@ -1175,7 +1175,7 @@ public class EquatePlugin1Test extends AbstractEquatePluginTest {
performAction("Convert To Char"); performAction("Convert To Char");
ListingTextField tf = (ListingTextField) cb.getCurrentField(); ListingTextField tf = (ListingTextField) cb.getCurrentField();
assertEquals("'\\x02'", tf.getFieldElement(0, 11).getText()); assertEquals("02h", tf.getFieldElement(0, 11).getText());
undo(program); undo(program);
tf = (ListingTextField) cb.getCurrentField(); tf = (ListingTextField) cb.getCurrentField();
@ -1184,7 +1184,7 @@ public class EquatePlugin1Test extends AbstractEquatePluginTest {
redo(program); redo(program);
tf = (ListingTextField) cb.getCurrentField(); tf = (ListingTextField) cb.getCurrentField();
assertEquals("'\\x02'", tf.getFieldElement(0, 11).getText()); assertEquals("02h", tf.getFieldElement(0, 11).getText());
} }
@Test @Test

View file

@ -173,14 +173,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
return null; return null;
} }
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf); if (!ENDIAN.isBigEndian(settings, buf)) {
bytes = ArrayUtilities.reverse(bytes);
if (!isBigEndian) {
byte[] flipped = new byte[size];
for (int i = 0; i < size; i++) {
flipped[i] = bytes[size - i - 1];
}
bytes = flipped;
} }
if (size > 8) { if (size > 8) {
@ -225,16 +219,17 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
return "??"; return "??";
} }
boolean isLE = !ENDIAN.isBigEndian(settings, buf); if (!ENDIAN.isBigEndian(settings, buf)) {
if (isLE) {
bytes = ArrayUtilities.reverse(bytes); bytes = ArrayUtilities.reverse(bytes);
} }
BigInteger value = new BigInteger(bytes);
if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) { if (getFormatSettingsDefinition().getFormat(settings) == FormatSettingsDefinition.CHAR) {
return StringDataInstance.getCharRepresentation(this, bytes, settings, !isLE); return StringDataInstance.getCharRepresentation(this, bytes, settings);
} }
return getRepresentation(new BigInteger(bytes), settings, 8 * length); return getRepresentation(value, settings, 8 * length);
} }
/** /**

View file

@ -366,11 +366,21 @@ public class BitFieldDataType extends AbstractDataType {
return big; return big;
} }
public BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) { private BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) {
if (effectiveBitSize == 0) { if (effectiveBitSize == 0) {
return BigInteger.ZERO; return BigInteger.ZERO;
} }
try { try {
byte[] bytes = new byte[storageSize];
if (buf.getBytes(bytes, 0) != storageSize) {
return null;
}
if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) {
bytes = ArrayUtilities.reverse(bytes);
}
BigInteger big = buf.getBigInteger(0, storageSize, false); BigInteger big = buf.getBigInteger(0, storageSize, false);
BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize); BigInteger pow = BigInteger.valueOf(2).pow(effectiveBitSize);
BigInteger mask = pow.subtract(BigInteger.ONE); BigInteger mask = pow.subtract(BigInteger.ONE);
@ -415,12 +425,8 @@ public class BitFieldDataType extends AbstractDataType {
} }
int bytesLen = BitFieldDataType.getMinimumStorageSize(bitSize); int bytesLen = BitFieldDataType.getMinimumStorageSize(bitSize);
byte[] bytes = DataConverter.getInstance(buf.isBigEndian()).getBytes(big, bytesLen); byte[] bytes = DataConverter.getInstance(buf.isBigEndian()).getBytes(big, bytesLen);
if (!EndianSettingsDefinition.ENDIAN.isBigEndian(settings, buf)) {
bytes = ArrayUtilities.reverse(bytes);
}
return StringDataInstance.getCharRepresentation(this, bytes, settings, return StringDataInstance.getCharRepresentation(this, bytes, settings);
buf.isBigEndian());
} }
return intDT.getRepresentation(big, settings, effectiveBitSize); return intDT.getRepresentation(big, settings, effectiveBitSize);

View file

@ -44,6 +44,9 @@ import ghidra.util.*;
* <p> * <p>
*/ */
public class StringDataInstance { public class StringDataInstance {
private static final int ASCII_MAX = 0x7f;
/** /**
* Returns true if the {@link Data} instance is a 'string'. * Returns true if the {@link Data} instance is a 'string'.
* *
@ -83,7 +86,7 @@ public class StringDataInstance {
return dt instanceof AbstractStringDataType || (dt instanceof Array && return dt instanceof AbstractStringDataType || (dt instanceof Array &&
ArrayStringable.getArrayStringable(((Array) dt).getDataType()) != null); ArrayStringable.getArrayStringable(((Array) dt).getDataType()) != null);
} }
/** /**
* Returns true if the {@link Data} instance is one of the many 'char' data types. * Returns true if the {@link Data} instance is one of the many 'char' data types.
* *
@ -105,16 +108,31 @@ public class StringDataInstance {
* <p> * <p>
* *
* @param dataType the {@link DataType} of the element containing the bytes (most likely a ByteDataType) * @param dataType the {@link DataType} of the element containing the bytes (most likely a ByteDataType)
* @param bytes the bytes to convert * @param bytes the big-endian ordered bytes to convert to a char representation
* @param settings the {@link Settings} object for the location where the bytes came from, or null * @param settings the {@link Settings} object for the location where the bytes came from, or null
* @param isBigEndian boolean flag indicating data is big endian
* @return formatted string (typically with quotes around the contents): single character: 'a', multiple characters: "a\x12bc" * @return formatted string (typically with quotes around the contents): single character: 'a', multiple characters: "a\x12bc"
*/ */
public static String getCharRepresentation(DataType dataType, byte[] bytes, Settings settings, public static String getCharRepresentation(DataType dataType, byte[] bytes, Settings settings) {
boolean isBigEndian) { if (bytes == null || bytes.length == 0) {
MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, isBigEndian); return UNKNOWN;
StringDataInstance sdi = }
new StringDataInstance(dataType, settings, memBuf, bytes.length);
// ignore leading 0 bytes
int lsbIndex = bytes.length - 1;
if (bytes[lsbIndex] >= 0 && bytes[lsbIndex] <= 0x7f) {
boolean isAsciiChar = true;
for (int i = 0; i < lsbIndex; i++) {
if (bytes[i] != 0) {
isAsciiChar = false;
}
}
if (isAsciiChar) {
bytes = new byte[] { bytes[lsbIndex] };
}
}
MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, true);
StringDataInstance sdi = new StringDataInstance(dataType, settings, memBuf, bytes.length);
return sdi.getCharRepresentation(); return sdi.getCharRepresentation();
} }