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
protected String convertToString(Program program, Scalar scalar, boolean isData) {
byte[] bytes = scalar.byteArrayValue();
return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null,
program.getMemory().isBigEndian());
return StringDataInstance.getCharRepresentation(ByteDataType.dataType, bytes, null);
}
}

View file

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

View file

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

View file

@ -173,14 +173,8 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
return null;
}
boolean isBigEndian = ENDIAN.isBigEndian(settings, buf);
if (!isBigEndian) {
byte[] flipped = new byte[size];
for (int i = 0; i < size; i++) {
flipped[i] = bytes[size - i - 1];
}
bytes = flipped;
if (!ENDIAN.isBigEndian(settings, buf)) {
bytes = ArrayUtilities.reverse(bytes);
}
if (size > 8) {
@ -225,16 +219,17 @@ public abstract class AbstractIntegerDataType extends BuiltIn implements ArraySt
return "??";
}
boolean isLE = !ENDIAN.isBigEndian(settings, buf);
if (isLE) {
if (!ENDIAN.isBigEndian(settings, buf)) {
bytes = ArrayUtilities.reverse(bytes);
}
BigInteger value = new BigInteger(bytes);
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;
}
public BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) {
private BigInteger getBigIntegerValue(MemBuffer buf, Settings settings) {
if (effectiveBitSize == 0) {
return BigInteger.ZERO;
}
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 pow = BigInteger.valueOf(2).pow(effectiveBitSize);
BigInteger mask = pow.subtract(BigInteger.ONE);
@ -415,12 +425,8 @@ public class BitFieldDataType extends AbstractDataType {
}
int bytesLen = BitFieldDataType.getMinimumStorageSize(bitSize);
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,
buf.isBigEndian());
return StringDataInstance.getCharRepresentation(this, bytes, settings);
}
return intDT.getRepresentation(big, settings, effectiveBitSize);

View file

@ -44,6 +44,9 @@ import ghidra.util.*;
* <p>
*/
public class StringDataInstance {
private static final int ASCII_MAX = 0x7f;
/**
* Returns true if the {@link Data} instance is a 'string'.
*
@ -105,16 +108,31 @@ public class StringDataInstance {
* <p>
*
* @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 isBigEndian boolean flag indicating data is big endian
* @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,
boolean isBigEndian) {
MemBuffer memBuf = new ByteMemBufferImpl(null, bytes, isBigEndian);
StringDataInstance sdi =
new StringDataInstance(dataType, settings, memBuf, bytes.length);
public static String getCharRepresentation(DataType dataType, byte[] bytes, Settings settings) {
if (bytes == null || bytes.length == 0) {
return UNKNOWN;
}
// 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();
}