MOVE ME to patch and re-describe: GT-3569

This commit is contained in:
Dan 2020-02-28 11:28:03 -05:00
parent 0a74b2b063
commit 8c9a727b56
3 changed files with 47 additions and 9 deletions

View file

@ -15,13 +15,20 @@
*/ */
package ghidra.app.plugin.assembler.sleigh.parse; package ghidra.app.plugin.assembler.sleigh.parse;
import java.util.Collections; import java.util.*;
import java.util.Set;
import org.apache.commons.collections4.IterableUtils;
/** /**
* An unsuccessful result from parsing * An unsuccessful result from parsing
*/ */
public class AssemblyParseErrorResult extends AssemblyParseResult { public class AssemblyParseErrorResult extends AssemblyParseResult {
/**
* The maximum number of suggestions to print when describing this error, e.g., when reported in
* exception messages.
*/
private static final int SUGGESTIONS_THRESHOLD = 10;
private final String buffer; private final String buffer;
private final Set<String> suggestions; private final Set<String> suggestions;
@ -40,15 +47,28 @@ public class AssemblyParseErrorResult extends AssemblyParseResult {
/** /**
* Get a description of the error * Get a description of the error
*
* @return a description * @return a description
*/ */
public String describeError() { public String describeError() {
return "Syntax Error: Expected " + suggestions + ". Got " + buffer; Collection<String> truncSuggestions;
if (suggestions.size() <= SUGGESTIONS_THRESHOLD) {
truncSuggestions = suggestions;
}
else {
truncSuggestions = new ArrayList<>();
for (String s : IterableUtils.boundedIterable(suggestions, SUGGESTIONS_THRESHOLD)) {
truncSuggestions.add(s);
}
truncSuggestions.add("...");
}
return "Syntax Error: Expected " + truncSuggestions + ". Got " + buffer;
} }
/** /**
* Get a set of suggested tokens that would have allowed parsing to continue * Get a set of suggested tokens that would have allowed parsing to continue
* @return the set *
* @return the token set
*/ */
public Set<String> getSuggestions() { public Set<String> getSuggestions() {
return Collections.unmodifiableSet(suggestions); return Collections.unmodifiableSet(suggestions);
@ -56,7 +76,8 @@ public class AssemblyParseErrorResult extends AssemblyParseResult {
/** /**
* Get the leftover contents of the input buffer when the error occurred * Get the leftover contents of the input buffer when the error occurred
* @return *
* @return the remaining buffer contents
*/ */
public String getBuffer() { public String getBuffer() {
return buffer; return buffer;

View file

@ -202,7 +202,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
long addr, String ctxstr) { long addr, String ctxstr) {
final AssemblyPatternBlock ctx = final AssemblyPatternBlock ctx =
(ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr)) (ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr))
.fillMask(); .fillMask();
dbg.println("Checking each: " + disassembly + " ctx:" + ctx); dbg.println("Checking each: " + disassembly + " ctx:" + ctx);
boolean gotOne = false; boolean gotOne = false;
boolean failedOne = false; boolean failedOne = false;
@ -303,7 +303,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
/** /**
* Run a test with the given checks * Run a test with the given checks
* *
* @param assembly the text to assembly * @param assembly the text to assemble
* @param instr an instruction pattern that must appear in the results * @param instr an instruction pattern that must appear in the results
* @param disassembly a set of acceptable disassembly texts * @param disassembly a set of acceptable disassembly texts
* @param addr the address for assembly and disassembly * @param addr the address for assembly and disassembly
@ -326,7 +326,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
} }
final AssemblyPatternBlock ctx = final AssemblyPatternBlock ctx =
(ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr)) (ctxstr == null ? context.getDefault() : AssemblyPatternBlock.fromString(ctxstr))
.fillMask(); .fillMask();
try { try {
String disstr; String disstr;
PseudoInstruction psins = disassemble(addr, ins.getVals(), ctx.getVals()); PseudoInstruction psins = disassemble(addr, ins.getVals(), ctx.getVals());
@ -398,7 +398,7 @@ public abstract class AbstractAssemblyTest extends AbstractGenericTest {
/** /**
* Run a test where one result must match a given instruction pattern, and all others must * Run a test where one result must match a given instruction pattern, and all others must
* disassemble exactly to the input * disassemble exactly to the input
* *
* @param assembly the input assembly * @param assembly the input assembly
* @param instr the instruction pattern * @param instr the instruction pattern
* @see AssemblyPatternBlock#fromString(String) * @see AssemblyPatternBlock#fromString(String)

View file

@ -15,6 +15,9 @@
*/ */
package ghidra.app.plugin.assembler.sleigh; package ghidra.app.plugin.assembler.sleigh;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test; import org.junit.Test;
import ghidra.app.plugin.assembler.*; import ghidra.app.plugin.assembler.*;
@ -31,6 +34,20 @@ public class x86AssemblyTest extends AbstractAssemblyTest {
return new LanguageID("x86:LE:64:default"); return new LanguageID("x86:LE:64:default");
} }
@Test
public void testReasonableErrorMessageLength() throws AssemblySemanticException {
Assembler assembler = Assemblers.getAssembler(lang);
Address addr = lang.getDefaultSpace().getAddress(DEFAULT_ADDR);
try {
assembler.assembleLine(addr, "UNLIKELY qword ptr [RAX],RBX");
fail(); // The exception must be thrown
}
catch (AssemblySyntaxException e) {
Msg.info(this, "Got expected syntax error: " + e);
assertTrue(e.getMessage().length() < 1000);
}
}
@Test @Test
public void testAssemble_ADD_m0x12_RAXm_RBX() { public void testAssemble_ADD_m0x12_RAXm_RBX() {
// Again, a little odd. Imm8 does not have the I+R form. // Again, a little odd. Imm8 does not have the I+R form.