summaryrefslogtreecommitdiff
path: root/scripts/fuzz_opt.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/fuzz_opt.py')
-rw-r--r--scripts/fuzz_opt.py72
1 files changed, 55 insertions, 17 deletions
diff --git a/scripts/fuzz_opt.py b/scripts/fuzz_opt.py
index 5effaad4b..bea4635ac 100644
--- a/scripts/fuzz_opt.py
+++ b/scripts/fuzz_opt.py
@@ -52,6 +52,10 @@ LOG_LIMIT = 125
# utilities
+def in_binaryen(*args):
+ return os.path.join(options.binaryen_root, *args)
+
+
def in_bin(tool):
return os.path.join(options.binaryen_root, 'bin', tool)
@@ -139,8 +143,17 @@ def run_vm(cmd):
raise
-def run_bynterp(wasm):
- return fix_output(run_vm([in_bin('wasm-opt'), wasm, '--fuzz-exec-before'] + FEATURE_OPTS))
+def run_bynterp(wasm, args):
+ # increase the interpreter stack depth, to test more things
+ os.environ['BINARYEN_MAX_INTERPRETER_DEPTH'] = '1000'
+ try:
+ return run_vm([in_bin('wasm-opt'), wasm] + FEATURE_OPTS + args)
+ finally:
+ del os.environ['BINARYEN_MAX_INTERPRETER_DEPTH']
+
+
+def run_d8(wasm):
+ return run_vm(['d8', in_binaryen('scripts', 'fuzz_shell.js'), '--', wasm])
# Each test case handler receives two wasm files, one before and one after some changes
@@ -166,7 +179,7 @@ class CompareVMs(TestCaseHandler):
def run_vms(self, js, wasm):
results = []
- results.append(run_bynterp(wasm))
+ results.append(fix_output(run_bynterp(wasm, ['--fuzz-exec-before'])))
results.append(fix_output(run_vm(['d8', js] + V8_OPTS + ['--', wasm])))
# append to add results from VMs
@@ -200,7 +213,7 @@ class CompareVMs(TestCaseHandler):
class FuzzExec(TestCaseHandler):
def handle_pair(self, before_wasm, after_wasm, opts):
# fuzz binaryen interpreter itself. separate invocation so result is easily fuzzable
- run([in_bin('wasm-opt'), before_wasm, '--fuzz-exec', '--fuzz-binary'] + opts)
+ run_bynterp(before_wasm, ['--fuzz-exec', '--fuzz-binary'])
# Check for determinism - the same command must have the same output
@@ -241,19 +254,44 @@ class Wasm2JS(TestCaseHandler):
class Bysyncify(TestCaseHandler):
- def handle(self, wasm):
- # run normally and run in an async manner, and compare
- before = run([in_bin('wasm-opt'), wasm, '--fuzz-exec'])
+ def handle_pair(self, before_wasm, after_wasm, opts):
+ # we must legalize in order to run in JS
+ run([in_bin('wasm-opt'), before_wasm, '--legalize-js-interface', '-o', before_wasm])
+ run([in_bin('wasm-opt'), after_wasm, '--legalize-js-interface', '-o', after_wasm])
+ before = fix_output(run_d8(before_wasm))
+ after = fix_output(run_d8(after_wasm))
+
# TODO: also something that actually does async sleeps in the code, say
# on the logging commands?
# --remove-unused-module-elements removes the bysyncify intrinsics, which are not valid to call
- cmd = [in_bin('wasm-opt'), wasm, '--bysyncify', '--remove-unused-module-elements', '-o', 'by.wasm']
- if random.random() < 0.5:
- cmd += ['--optimize-level=3'] # TODO: more
- run(cmd)
- after = run([in_bin('wasm-opt'), 'by.wasm', '--fuzz-exec'])
- after = '\n'.join([line for line in after.splitlines() if '[fuzz-exec] calling $bysyncify' not in line])
- compare(before, after, 'Bysyncify')
+
+ def do_bysyncify(wasm):
+ cmd = [in_bin('wasm-opt'), wasm, '--bysyncify', '-o', 't.wasm']
+ if random.random() < 0.5:
+ cmd += ['--optimize-level=%d' % random.randint(1, 3)]
+ if random.random() < 0.5:
+ cmd += ['--shrink-level=%d' % random.randint(1, 2)]
+ run(cmd)
+ out = run_d8('t.wasm')
+ # emit some status logging from bysyncify
+ print(out.splitlines()[-1])
+ # ignore the output from the new bysyncify API calls - the ones with asserts will trap, too
+ for ignore in ['[fuzz-exec] calling $bysyncify_start_unwind\nexception!\n',
+ '[fuzz-exec] calling $bysyncify_start_unwind\n',
+ '[fuzz-exec] calling $bysyncify_start_rewind\nexception!\n',
+ '[fuzz-exec] calling $bysyncify_start_rewind\n',
+ '[fuzz-exec] calling $bysyncify_stop_rewind\n',
+ '[fuzz-exec] calling $bysyncify_stop_unwind\n']:
+ out = out.replace(ignore, '')
+ out = '\n'.join([l for l in out.splitlines() if 'bysyncify: ' not in l])
+ return fix_output(out)
+
+ before_bysyncify = do_bysyncify(before_wasm)
+ after_bysyncify = do_bysyncify(after_wasm)
+
+ compare(before, after, 'Bysyncify (before/after)')
+ compare(before, before_bysyncify, 'Bysyncify (before/before_bysyncify)')
+ compare(before, after_bysyncify, 'Bysyncify (before/after_bysyncify)')
# The global list of all test case handlers
@@ -262,19 +300,19 @@ testcase_handlers = [
FuzzExec(),
CheckDeterminism(),
Wasm2JS(),
- # TODO Bysyncify(),
+ Bysyncify(),
]
# Do one test, given an input file for -ttf and some optimizations to run
-def test_one(infile, opts):
+def test_one(random_input, opts):
randomize_pass_debug()
bytes = 0
# fuzz vms
# gather VM outputs on input file
- run([in_bin('wasm-opt'), infile, '-ttf', '-o', 'a.wasm'] + FUZZ_OPTS + FEATURE_OPTS)
+ run([in_bin('wasm-opt'), random_input, '-ttf', '-o', 'a.wasm'] + FUZZ_OPTS + FEATURE_OPTS)
wasm_size = os.stat('a.wasm').st_size
bytes += wasm_size
print('pre js size :', os.stat('a.js').st_size, ' wasm size:', wasm_size)