diff options
Diffstat (limited to 'scripts/fuzz_relooper.py')
-rwxr-xr-x | scripts/fuzz_relooper.py | 146 |
1 files changed, 102 insertions, 44 deletions
diff --git a/scripts/fuzz_relooper.py b/scripts/fuzz_relooper.py index 45ead4cf2..151f39d61 100755 --- a/scripts/fuzz_relooper.py +++ b/scripts/fuzz_relooper.py @@ -22,6 +22,11 @@ import difflib import os import random import subprocess +import time + +seed_init = long(time.time()) +seed_init *= seed_init +seed_init %= (2**32) if os.environ.get('LD_LIBRARY_PATH'): os.environ['LD_LIBRARY_PATH'] += os.pathsep + 'lib' @@ -32,12 +37,35 @@ counter = 0 while True: # Random decisions + seed = seed_init + random.seed(seed) + seed_init += 1 num = random.randint(2, 250) density = random.random() * random.random() + code_likelihood = random.random() + code_max = random.randint(0, num if random.random() < 0.5 else 3) + max_printed = random.randint(1, num if random.random() < 0.5 else 3) max_decision = num * 20 decisions = [random.randint(1, max_decision) for x in range(num * 3)] branches = [0] * num defaults = [0] * num + branch_codes = [0] * num # code on the branch, which may alter the global state + + # with some probability print the same id for different blocks, + # as the printing is the block contents - allow merging etc. opts + def printed_id(i): + if random.random() < 0.5: + return i + return i % max_printed + + printed_ids = [printed_id(i) for i in range(num)] + + def random_code(): + if code_max == 0 or random.random() > code_likelihood: + return 0 # no code + # A random number to perturb/increment the global state + return random.randint(1, code_max) + for i in range(num): b = set([]) bs = random.randint(1, max(1, @@ -48,8 +76,9 @@ while True: defaults[i] = random.choice(b) b.remove(defaults[i]) branches[i] = b + branch_codes[i] = [random_code() for item in range(len(b) + 1)] # one for each branch, plus the default optimize = random.random() < 0.5 - print counter, ':', num, density, optimize + print counter, ':', num, density, optimize, code_likelihood, code_max, max_printed, ', seed =', seed counter += 1 for temp in ['fuzz.wasm', 'fuzz.wast', 'fast.txt', 'fuzz.slow.js', @@ -66,7 +95,7 @@ var state; var decisions = %s; var index = 0; function check() { - if (index == decisions.length) throw 'HALT'; + if (index >= decisions.length) throw 'HALT'; console.log('(i32.const ' + (-decisions[index]) + ')'); return decisions[index++]; } @@ -97,8 +126,8 @@ int main() { // if the end, halt BinaryenExpressionRef halter = BinaryenIf(module, BinaryenBinary(module, - BinaryenEqInt32(), - BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), + BinaryenGeUInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4 * %d)) // jumps of 4 bytes ), @@ -111,11 +140,11 @@ int main() { BinaryenConst(module, BinaryenLiteralInt32(4)), BinaryenBinary(module, BinaryenAddInt32(), - BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))), BinaryenConst(module, BinaryenLiteralInt32(4)) ), - BinaryenInt32() + BinaryenTypeInt32() ); // optionally, print the return value @@ -124,48 +153,57 @@ int main() { BinaryenSubInt32(), BinaryenConst(module, BinaryenLiteralInt32(0)), BinaryenLoad(module, - 4, 0, 4, 0, BinaryenInt32(), - BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))) ) ) }; BinaryenExpressionRef debugger; if (1) debugger = BinaryenCall(module, "print", args, 1, - BinaryenNone()); + BinaryenTypeNone()); else debugger = BinaryenNop(module); // return the decision. need to subtract 4 that we just added, // and add 8 since that's where we start, so overall offset 4 BinaryenExpressionRef returner = BinaryenLoad(module, - 4, 0, 4, 0, BinaryenInt32(), - BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(), + 4, 0, 4, 0, BinaryenTypeInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), BinaryenConst(module, BinaryenLiteralInt32(4))) ); BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger, returner }; BinaryenExpressionRef checkBody = BinaryenBlock(module, - NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef) + NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef), + BinaryenTypeInt32() ); BinaryenFunctionTypeRef i = BinaryenAddFunctionType(module, "i", - BinaryenInt32(), + BinaryenTypeInt32(), NULL, 0); BinaryenAddFunction(module, "check", i, NULL, 0, checkBody); // contents of main() begin here - RelooperRef relooper = RelooperCreate(); + RelooperRef relooper = RelooperCreate(module); ''' % len(decisions) - for i in range(0, num): + for i in range(num): slow += ' case %d: console.log("(i32.const %d)"); state = check(); \n' % ( - i, i) + i, printed_ids[i]) b = branches[i] + bc = branch_codes[i] + + def get_phi(j): + phi = '' + if bc[j]: + phi = 'index += %d; ' % bc[j] + return phi + for j in range(len(b)): - slow += ' if (state %% %d == %d) { label = %d; break }\n' % ( - len(b) + 1, j, b[j]) # TODO: split range 1-n into these options - slow += ' label = %d; break\n' % defaults[i] + slow += ' if (state %% %d == %d) { %s label = %d; break }\n' % ( + len(b) + 1, j, get_phi(j), b[j]) # TODO: split range 1-n into these options + slow += ' %slabel = %d; break\n' % (get_phi(-1), defaults[i]) use_switch = [random.random() < 0.5 for i in range(num)] @@ -177,25 +215,25 @@ int main() { BinaryenConst(module, BinaryenLiteralInt32(%d)) }; BinaryenExpressionRef list[] = { - BinaryenCall(module, "print", args, 1, BinaryenNone()), + BinaryenCall(module, "print", args, 1, BinaryenTypeNone()), BinaryenSetLocal(module, 0, BinaryenCall(module, "check", NULL, 0, - BinaryenInt32())) + BinaryenTypeInt32())) }; -''' % (i, i) +''' % (i, printed_ids[i]) if use_switch[i]: fast += ''' b%d = RelooperAddBlockWithSwitch(relooper, - BinaryenBlock(module, NULL, list, 2), + BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone()), BinaryenBinary(module, BinaryenRemUInt32(), - BinaryenGetLocal(module, 0, BinaryenInt32()), + BinaryenGetLocal(module, 0, BinaryenTypeInt32()), BinaryenConst(module, BinaryenLiteralInt32(%d)) ) ); ''' % (i, len(branches[i]) + 1) else: # non-switch fast += ''' - b%d = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2)); + b%d = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2, BinaryenTypeNone())); ''' % i fast += ''' } @@ -203,6 +241,26 @@ int main() { for i in range(num): b = branches[i] + bc = branch_codes[i] + + def get_phi(j): + phi = 'NULL' + if bc[j]: + # increment the index of global state + phi = ''' + BinaryenStore(module, + 4, 0, 0, + BinaryenConst(module, BinaryenLiteralInt32(4)), + BinaryenBinary(module, + BinaryenAddInt32(), + BinaryenLoad(module, 4, 0, 0, 0, BinaryenTypeInt32(), + BinaryenConst(module, BinaryenLiteralInt32(4))), + BinaryenConst(module, BinaryenLiteralInt32(4 * %d)) + ), + BinaryenTypeInt32() + )''' % bc[j] + return phi + for j in range(len(b)): if use_switch[i]: total = len(b) + 1 @@ -212,34 +270,33 @@ int main() { { BinaryenIndex values[] = { %s }; RelooperAddBranchForSwitch(b%d, b%d, values, - sizeof(values) / sizeof(BinaryenIndex), NULL); + sizeof(values) / sizeof(BinaryenIndex), %s); } -''' % (values, i, b[j]) +''' % (values, i, b[j], get_phi(j)) else: # non-switch fast += ''' RelooperAddBranch(b%d, b%d, BinaryenBinary(module, BinaryenEqInt32(), BinaryenBinary(module, BinaryenRemUInt32(), - BinaryenGetLocal(module, 0, BinaryenInt32()), + BinaryenGetLocal(module, 0, BinaryenTypeInt32()), BinaryenConst(module, BinaryenLiteralInt32(%d)) ), BinaryenConst(module, BinaryenLiteralInt32(%d)) - ), NULL); -''' % (i, b[j], len(b) + 1, j) + ), %s); +''' % (i, b[j], len(b) + 1, j, get_phi(j)) # default branch if use_switch[i]: fast += ''' - RelooperAddBranchForSwitch(b%d, b%d, NULL, 0, NULL); -''' % (i, defaults[i]) + RelooperAddBranchForSwitch(b%d, b%d, NULL, 0, %s); +''' % (i, defaults[i], get_phi(-1)) else: fast += ''' - RelooperAddBranch(b%d, b%d, NULL, NULL); -''' % (i, defaults[i]) + RelooperAddBranch(b%d, b%d, NULL, %s); +''' % (i, defaults[i], get_phi(-1)) fast += ''' - BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1, - module); + BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1); int decisions[] = { %s }; int numDecisions = sizeof(decisions)/sizeof(int); @@ -254,33 +311,34 @@ int main() { 4, 0, 0, BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)), BinaryenConst(module, BinaryenLiteralInt32(decisions[i])), - BinaryenInt32() + BinaryenTypeInt32() ); } } full[numDecisions] = body; BinaryenExpressionRef all = BinaryenBlock(module, NULL, full, - numDecisions + 1); + numDecisions + 1, + BinaryenTypeNone()); BinaryenFunctionTypeRef v = BinaryenAddFunctionType(module, "v", - BinaryenNone(), + BinaryenTypeNone(), NULL, 0); // locals: state, free-for-label - BinaryenType localTypes[] = { BinaryenInt32(), BinaryenInt32() }; + BinaryenType localTypes[] = { BinaryenTypeInt32(), BinaryenTypeInt32() }; BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", v, localTypes, 2, all); BinaryenSetStart(module, theMain); // import - BinaryenType iparams[] = { BinaryenInt32() }; + BinaryenType iparams[] = { BinaryenTypeInt32() }; BinaryenFunctionTypeRef vi = BinaryenAddFunctionType(module, "vi", - BinaryenNone(), + BinaryenTypeNone(), iparams, 1); - BinaryenAddImport(module, "print", "spectest", "print", vi); + BinaryenAddFunctionImport(module, "print", "spectest", "print", vi); // memory - BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0); + BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0, 0); // optionally, optimize if (%d) BinaryenModuleOptimize(module); |