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:
commit
fe83ce5262
@ -126,6 +126,38 @@ def main():
|
|||||||
currentOneOf = currentOneOf[:-1]
|
currentOneOf = currentOneOf[:-1]
|
||||||
return (OneOfs, lastRead)
|
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)
|
initial = runCandidate(test)
|
||||||
if (not args.search) and (not checks(initial)):
|
if (not args.search) and (not checks(initial)):
|
||||||
print("STARTING TEST DOES NOT SATISFY REDUCTION CRITERIA")
|
print("STARTING TEST DOES NOT SATISFY REDUCTION CRITERIA")
|
||||||
@ -133,15 +165,25 @@ def main():
|
|||||||
|
|
||||||
with open(test, 'rb') as test:
|
with open(test, 'rb') as test:
|
||||||
currentTest = bytearray(test.read())
|
currentTest = bytearray(test.read())
|
||||||
|
original = bytearray(currentTest)
|
||||||
|
|
||||||
print("ORIGINAL TEST HAS", len(currentTest), "BYTES")
|
print("ORIGINAL TEST HAS", len(currentTest), "BYTES")
|
||||||
|
|
||||||
|
fixUp(currentTest, rangeConversions(initial))
|
||||||
|
r = writeAndRunCandidate(currentTest)
|
||||||
|
assert(checks(r))
|
||||||
|
|
||||||
s = structure(initial)
|
s = structure(initial)
|
||||||
if (s[1]+1) < len(currentTest):
|
if (s[1]+1) < len(currentTest):
|
||||||
print("LAST BYTE READ IS", s[1])
|
print("LAST BYTE READ IS", s[1])
|
||||||
print("SHRINKING TO IGNORE UNREAD BYTES")
|
print("SHRINKING TO IGNORE UNREAD BYTES")
|
||||||
currentTest = currentTest[:s[1]+1]
|
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))
|
initialSize = float(len(currentTest))
|
||||||
iteration = 0
|
iteration = 0
|
||||||
changed = True
|
changed = True
|
||||||
@ -242,7 +284,7 @@ def main():
|
|||||||
if (not args.fast) and (not changed):
|
if (not args.fast) and (not changed):
|
||||||
for b1 in range(0, len(currentTest)-4):
|
for b1 in range(0, len(currentTest)-4):
|
||||||
if args.verbose:
|
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):
|
for b2 in range(b1+2, len(currentTest)-4):
|
||||||
v1 = (currentTest[b1], currentTest[b1+1])
|
v1 = (currentTest[b1], currentTest[b1+1])
|
||||||
v2 = (currentTest[b2], currentTest[b2+1])
|
v2 = (currentTest[b2], currentTest[b2+1])
|
||||||
@ -279,6 +321,7 @@ def main():
|
|||||||
with open(out, 'wb') as outf:
|
with open(out, 'wb') as outf:
|
||||||
outf.write(currentTest)
|
outf.write(currentTest)
|
||||||
s = structure(r)
|
s = structure(r)
|
||||||
|
fixUp(currentTest, rangeConversions(r))
|
||||||
else:
|
else:
|
||||||
print("*" * 80)
|
print("*" * 80)
|
||||||
print("NO (MORE) REDUCTIONS FOUND")
|
print("NO (MORE) REDUCTIONS FOUND")
|
||||||
|
|||||||
@ -295,6 +295,11 @@ DEEPSTATE_INLINE static void DeepState_Check(int expr) {
|
|||||||
} \
|
} \
|
||||||
if ((x < low) || (x > high)) { \
|
if ((x < low) || (x > high)) { \
|
||||||
const tname size = (high - low) + 1; \
|
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 low + ((x % size + size) % size); \
|
||||||
} \
|
} \
|
||||||
return x; \
|
return x; \
|
||||||
@ -598,8 +603,10 @@ static int DeepState_RunTestNoFork(struct DeepState_TestInfo *test) {
|
|||||||
} else {
|
} else {
|
||||||
DeepState_LogFormat(DeepState_LogTrace, "Passed: %s", test->test_name);
|
DeepState_LogFormat(DeepState_LogTrace, "Passed: %s", test->test_name);
|
||||||
if (HAS_FLAG_output_test_dir) {
|
if (HAS_FLAG_output_test_dir) {
|
||||||
|
if (!FLAGS_fuzz || FLAGS_fuzz_save_passing) {
|
||||||
DeepState_SavePassingTest();
|
DeepState_SavePassingTest();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return(DeepState_TestRunPass);
|
return(DeepState_TestRunPass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user