GP-2435 fix exception in QueryOptionService if secondary isn't an intstr

This commit is contained in:
dev747368 2022-08-08 21:36:10 +00:00
parent c523b2b9d4
commit 8b924f718e
4 changed files with 83 additions and 39 deletions

View file

@ -15,9 +15,10 @@
*/
package ghidra.app.util.opinion;
import java.io.IOException;
import java.util.*;
import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.*;
@ -206,53 +207,60 @@ public class QueryOpinionService {
return queryResult;
}
static boolean secondaryAttributeMatches(String eFlagsDecimalString, String attribute) {
// eFlagDecimalString is the elf e_flags value, as a decimal string
// sa is the secondary attribute string from the opinion file,
// and it must start with "0x" or "0b"
if (attribute == null) {
/**
* Match a secondaryKey value string against a binary or hex formatted constraint.
* <p>
* The constraint value needs to be patterned as:
* <li>Binary: "0b1110_0001 111..." (spaces and "_" ignored, dots are wildcards)
* <li>Hex: "0xaabb_ccdd" (hex digits, spaces and "_" ignored)
*
* @param secondaryKey decimal integer string that is being searched for
* @param constraint value or pattern that the secondaryKey is being compared against
* @return boolean true if the secondaryKey matches the constraint; false if it doesn't match
* or if the constraint isn't a binary or hex constraint, or if the secondaryKey value isn't
* an integer
*/
static boolean secondaryAttributeMatches(String secondaryKey, String constraint) {
if (constraint == null) {
return false;
}
if (!StringUtils.startsWithAny(attribute.toLowerCase(), "0x", "0b")) {
int secondaryKeyInt;
try {
secondaryKeyInt = Integer.parseInt(secondaryKey);
}
catch (NumberFormatException e) {
return false;
}
int eFlagsInt = Integer.parseInt(eFlagsDecimalString);
String eFlagsBinaryString = Integer.toBinaryString(eFlagsInt);
if (eFlagsBinaryString == null) {
return false;
}
eFlagsBinaryString = StringUtils.leftPad(eFlagsBinaryString, 32, "0");
String eFlagsHexString = Integer.toHexString(eFlagsInt);
eFlagsHexString = StringUtils.leftPad(eFlagsHexString, 8, "0");
// Remove '_' and whitespace from the attribute string
String cleaned = attribute.replace("_", "").replaceAll("\\s+", "").trim();
String prefix = cleaned.substring(0, 2);
String value = cleaned.substring(2);
if (prefix.toLowerCase().startsWith("0x")) {
// It's a hex string
value = StringUtils.leftPad(value, 8, "0");
return value.equals(eFlagsHexString);
}
// It's a binary string
value = StringUtils.leftPad(value, 32, "0");
for (int i = 0; i < 32; i++) {
char c = value.charAt(i);
if (c == '.') { // wildcard
continue;
constraint = constraint.replaceAll("[_\\s]+", "").trim().toLowerCase();
if (constraint.startsWith("0x")) { // Hex constraint string
try {
int hexConstraint = Integer.parseUnsignedInt(constraint.substring(2), 16);
return secondaryKeyInt == hexConstraint;
}
if (eFlagsBinaryString.charAt(i) != c) {
return false;
catch (NumberFormatException e) {
// fall thru, return false
}
return false;
}
else if (constraint.startsWith("0b")) { // Binary constraint string
String secondaryKeyBinaryString = Integer.toBinaryString(secondaryKeyInt);
secondaryKeyBinaryString = StringUtils.leftPad(secondaryKeyBinaryString, 32, "0");
return true;
String constraintBinaryString = StringUtils.leftPad(constraint.substring(2), 32, "0");
for (int i = 0; i < 32; i++) {
char c = constraintBinaryString.charAt(i);
if (c == '.') { // wildcard
continue;
}
if (secondaryKeyBinaryString.charAt(i) != c) {
return false;
}
}
return true;
}
return false;
}
}

View file

@ -50,4 +50,22 @@ public class QueryOpinionServiceTest {
}
@Test
public void testHexConstraint() {
assertTrue(QueryOpinionService.secondaryAttributeMatches("85", "0x55"));
assertTrue(QueryOpinionService.secondaryAttributeMatches("-1", "0xff ff_ff ff"));
}
@Test
public void testNotBinaryOrHexConstraint() {
assertFalse(QueryOpinionService.secondaryAttributeMatches("1", "not_a_valid_constraint"));
assertFalse(QueryOpinionService.secondaryAttributeMatches("1", "0b1x"));
assertFalse(QueryOpinionService.secondaryAttributeMatches("1", ""));
}
@Test
public void testNotIntegerKey() {
assertFalse(QueryOpinionService.secondaryAttributeMatches("abc", "0x1"));
assertFalse(QueryOpinionService.secondaryAttributeMatches("", "0b...."));
}
}

View file

@ -1,4 +1,13 @@
<opinions>
<!--
NOTE: secondary key constraints can be matched at the bit level or as a hex value (if the
key is an integer value).
When matching at the bit level, prefix the secondary key constraint value with "0b", followed
by a sequence of 0's and 1's to specify the key value. Dots (".") can be used as a wild card
for individual bits. Space and underscores ("_") are ignored and can be used for formatting.
When matching a hex value, prefix the secondary key constraint value with "0x", followed
by the hex value. No wildcarding is supported.
-->
<constraint loader="Portable Executable (PE)">
<constraint compilerSpecID="windows">
<constraint primary="448" processor="ARM" endian="little" size="32" variant="v8" />

View file

@ -1,4 +1,13 @@
<opinions>
<!--
NOTE: secondary key constraints can be matched at the bit level or as a hex value (if the
key is an integer value).
When matching at the bit level, prefix the secondary key constraint value with "0b", followed
by a sequence of 0's and 1's to specify the key value. Dots (".") can be used as a wild card
for individual bits. Space and underscores ("_") are ignored and can be used for formatting.
When matching a hex value, prefix the secondary key constraint value with "0x", followed
by the hex value. No wildcarding is supported.
-->
<constraint loader="Portable Executable (PE)" compilerSpecID="windows">
<constraint primary="352" processor="MIPS" endian="big" size="32" variant="default" /> <!-- R3000 -->
<constraint primary="354" processor="MIPS" endian="little" size="32" variant="default" /> <!-- R3000 -->