Merge pull request #186 from trailofbits/fixup_ranges_in_reducer

Speed up reducer by figuring out converted bytes for ranges without trying byte reduces
This commit is contained in:
Alex Groce 2019-05-17 12:02:13 -07:00 committed by GitHub
commit fe83ce5262
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 2 deletions

View File

@ -126,6 +126,38 @@ def main():
currentOneOf = currentOneOf[:-1]
return (OneOfs, lastRead)
def rangeConversions(result):
conversions = []
startedMulti = False
multiFirst = None
for line in result:
if "Reading byte at" in line:
lastRead = int(line.split()[-1])
if "STARTING MULTI-BYTE READ" in line:
startedMulti = True
if startedMulti and (multiFirst is None) and ("Reading byte at" in line):
multiFirst = lastRead
if "FINISHED MULTI-BYTE READ" in line:
currentMulti = (multiFirst, lastRead)
startedMulti = False
multiFirst = None
if "Converting out-of-range value" in line:
conversions.append((currentMulti, int(line.split()[-1])))
return conversions
def fixUp(test, conversions):
numConversions = 0
for (pos, value) in conversions:
if pos[1] >= len(test):
break
if value < 255:
numConversions += 1
for b in range(pos[0], pos[1]):
test[b] = 0
test[pos[1]] = value
if numConversions > 0:
print("APPLIED", numConversions, "RANGE CONVERSIONS")
initial = runCandidate(test)
if (not args.search) and (not checks(initial)):
print("STARTING TEST DOES NOT SATISFY REDUCTION CRITERIA")
@ -133,15 +165,25 @@ def main():
with open(test, 'rb') as test:
currentTest = bytearray(test.read())
original = bytearray(currentTest)
print("ORIGINAL TEST HAS", len(currentTest), "BYTES")
fixUp(currentTest, rangeConversions(initial))
r = writeAndRunCandidate(currentTest)
assert(checks(r))
s = structure(initial)
if (s[1]+1) < len(currentTest):
print("LAST BYTE READ IS", s[1])
print("SHRINKING TO IGNORE UNREAD BYTES")
currentTest = currentTest[:s[1]+1]
if currentTest != original:
print("WRITING REDUCED TEST WITH", len(currentTest), "BYTES TO", out)
with open(out, 'wb') as outf:
outf.write(currentTest)
initialSize = float(len(currentTest))
iteration = 0
changed = True
@ -242,7 +284,7 @@ def main():
if (not args.fast) and (not changed):
for b1 in range(0, len(currentTest)-4):
if args.verbose:
print("TRYING BYTE PATTERN SEARCH FROM BYTE", str(b) + "...")
print("TRYING BYTE PATTERN SEARCH FROM BYTE", str(b1) + "...")
for b2 in range(b1+2, len(currentTest)-4):
v1 = (currentTest[b1], currentTest[b1+1])
v2 = (currentTest[b2], currentTest[b2+1])
@ -279,6 +321,7 @@ def main():
with open(out, 'wb') as outf:
outf.write(currentTest)
s = structure(r)
fixUp(currentTest, rangeConversions(r))
else:
print("*" * 80)
print("NO (MORE) REDUCTIONS FOUND")

View File

@ -295,6 +295,11 @@ DEEPSTATE_INLINE static void DeepState_Check(int expr) {
} \
if ((x < low) || (x > high)) { \
const tname size = (high - low) + 1; \
if (FLAGS_verbose_reads) { \
if (x != (low + ((x % size + size) % size))) { \
printf("Converting out-of-range value to %u\n", (unsigned int)(low + ((x % size + size) % size))); \
} \
} \
return low + ((x % size + size) % size); \
} \
return x; \
@ -598,7 +603,9 @@ static int DeepState_RunTestNoFork(struct DeepState_TestInfo *test) {
} else {
DeepState_LogFormat(DeepState_LogTrace, "Passed: %s", test->test_name);
if (HAS_FLAG_output_test_dir) {
DeepState_SavePassingTest();
if (!FLAGS_fuzz || FLAGS_fuzz_save_passing) {
DeepState_SavePassingTest();
}
}
return(DeepState_TestRunPass);
}