summaryrefslogtreecommitdiff
path: root/scripts/fuzz_relooper.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/fuzz_relooper.py')
-rwxr-xr-xscripts/fuzz_relooper.py146
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);