Merge pull request #114 from trailofbits/multibyte_reduction
Allow multibyte pattern reductions
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Intelligently reduce test case")
|
||||
@@ -40,6 +41,13 @@ def main():
|
||||
"--search", action="store_true", help="Allow initial test to not satisfy criteria (search for test).",
|
||||
default=None)
|
||||
|
||||
parser.add_argument(
|
||||
"--timeout", type=int, help="After this amount of time (in seconds), give up on reduction.",
|
||||
default=1200)
|
||||
|
||||
class TimeoutException(Exception):
|
||||
pass
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
deepstate = args.binary
|
||||
@@ -48,7 +56,11 @@ def main():
|
||||
checkString = args.criteria
|
||||
whichTest = args.which_test
|
||||
|
||||
start = time.time()
|
||||
|
||||
def runCandidate(candidate):
|
||||
if (time.time() - start) > args.timeout:
|
||||
raise TimeoutException
|
||||
with open(".reducer.out", 'w') as outf:
|
||||
cmd = [deepstate + " --input_test_file " +
|
||||
candidate + " --verbose_reads"]
|
||||
@@ -111,61 +123,94 @@ def main():
|
||||
currentTest = currentTest[:s[1]+1]
|
||||
|
||||
changed = True
|
||||
while changed:
|
||||
changed = False
|
||||
try:
|
||||
while changed:
|
||||
changed = False
|
||||
|
||||
cuts = s[0]
|
||||
for c in cuts:
|
||||
newTest = currentTest[:c[0]] + currentTest[c[1]+1:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("ONEOF REMOVAL REDUCED TEST TO", len(newTest), "BYTES")
|
||||
changed = True
|
||||
break
|
||||
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
for v in range(b+1, len(currentTest)):
|
||||
newTest = currentTest[:b] + currentTest[v:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE RANGE REMOVAL REDUCED TEST TO", len(newTest), "BYTES")
|
||||
changed = True
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
for v in range(0, currentTest[b]):
|
||||
newTest = bytearray(currentTest)
|
||||
newTest[b] = v
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE REDUCTION: BYTE", b, "FROM", currentTest[b], "TO", v)
|
||||
changed = True
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
if currentTest[b] == 0:
|
||||
continue
|
||||
newTest = bytearray(currentTest)
|
||||
newTest[b] = currentTest[b]-1
|
||||
newTest = newTest[:b+1] + newTest[b+2:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
cuts = s[0]
|
||||
for c in cuts:
|
||||
newTest = currentTest[:c[0]] + currentTest[c[1]+1:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE REDUCE AND DELETE AT BYTE", b)
|
||||
print("ONEOF REMOVAL REDUCED TEST TO", len(newTest), "BYTES")
|
||||
changed = True
|
||||
break
|
||||
|
||||
if changed:
|
||||
currentTest = newTest
|
||||
s = structure(r)
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
for v in range(b+1, len(currentTest)):
|
||||
newTest = currentTest[:b] + currentTest[v:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE RANGE REMOVAL REDUCED TEST TO", len(newTest), "BYTES")
|
||||
changed = True
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
|
||||
print("NO REDUCTIONS FOUND")
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
for v in range(0, currentTest[b]):
|
||||
newTest = bytearray(currentTest)
|
||||
newTest[b] = v
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE REDUCTION: BYTE", b, "FROM", currentTest[b], "TO", v)
|
||||
changed = True
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
|
||||
if not changed:
|
||||
for b in range(0, len(currentTest)):
|
||||
if currentTest[b] == 0:
|
||||
continue
|
||||
newTest = bytearray(currentTest)
|
||||
newTest[b] = currentTest[b]-1
|
||||
newTest = newTest[:b+1] + newTest[b+2:]
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE REDUCE AND DELETE AT BYTE", b)
|
||||
changed = True
|
||||
break
|
||||
|
||||
if not changed:
|
||||
for b1 in range(0, len(currentTest)-4):
|
||||
for b2 in range(b1+2, len(currentTest)-4):
|
||||
v1 = (currentTest[b1], currentTest[b1+1])
|
||||
v2 = (currentTest[b2], currentTest[b2+1])
|
||||
if (v1 == v2):
|
||||
ba = bytearray(v1)
|
||||
part1 = currentTest[:b1]
|
||||
part2 = currentTest[b1+2:b2]
|
||||
part3 = currentTest[b2+2:]
|
||||
banews = []
|
||||
banews.append(ba[0:1])
|
||||
banews.append(ba[1:2])
|
||||
if ba[0] > 0:
|
||||
banews.append(bytearray([ba[0]-1, ba[1]]))
|
||||
banews.append(bytearray([ba[0]-1]))
|
||||
if ba[1] > 0:
|
||||
banews.append(bytearray([ba[0], ba[1]-1]))
|
||||
for banew in banews:
|
||||
newTest = part1 + banew + part2 + banew + part3
|
||||
r = writeAndRunCandidate(newTest)
|
||||
if checks(r):
|
||||
print("BYTE PATTERN", tuple(ba), "AT", b1, "AND", b2, "CHANGED TO", tuple(banew))
|
||||
changed = True
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
if changed:
|
||||
break
|
||||
|
||||
if changed:
|
||||
currentTest = newTest
|
||||
s = structure(r)
|
||||
else:
|
||||
print("NO (MORE) REDUCTIONS FOUND")
|
||||
except TimeoutException:
|
||||
print("REDUCTION TIMED OUT AFTER", args.timeout, "SECONDS")
|
||||
|
||||
if (s[1] + 1) > len(currentTest):
|
||||
print("PADDING TEST WITH", (s[1] + 1) - len(currentTest), "ZEROS")
|
||||
|
||||
Reference in New Issue
Block a user