1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
import random, subprocess, difflib
while True:
# Random decisions
num = random.randint(2, 250)
density = random.random() * random.random()
decisions = [random.randint(1, num*20) for x in range(num*3)]
branches = [0]*num
defaults = [0]*num
for i in range(num):
b = set([])
bs = random.randint(1, max(1, round(density*random.random()*(num-1))))
for j in range(bs):
b.add(random.randint(1, num-1))
b = list(b)
defaults[i] = random.choice(b)
b.remove(defaults[i])
branches[i] = b
print num, density
for temp in ['fuzz', 'fuzz.fast.js', 'fuzz.slow.js', 'fuzz.cpp']:
try:
os.unlink(temp)
except:
pass
# parts
entry = '''print('entry'); var label; var state; var modded; var decisions = %s; var index = 0; function check() { if (index == decisions.length) throw 'HALT'; return decisions[index++] }''' % str(decisions)
slow = entry + '\n'
for i in range(len(branches[0])):
if i > 0: slow += 'else '
b = branches[0]
slow += 'if (modded == %d) { label = %d; }\n' % (i, b[i]) # TODO: split range 1-n into these options
if len(branches[0]): slow += 'else '
slow += 'label = %d;\n' % defaults[0]
slow += '''
while(1) switch(label) {
'''
fast = '''
#include <stdlib.h>
#include "Relooper.h"
int main() {
char *buffer = (char*)malloc(10*1024*1024);
Relooper::SetOutputBuffer(buffer, 10*1024*1024);
'''
for i in range(1, num):
slow += ' case %d: print(%d); state = check(); modded = state %% %d\n' % (i, i, len(branches[i])+1)
b = branches[i]
for j in range(len(b)):
slow += ' if (modded == %d) { label = %d; break }\n' % (j, b[j]) # TODO: split range 1-n into these options
slow += ' label = %d; break\n' % defaults[i]
branch_vars = []
for i in range(num):
branch_var = '"modded"' if len(branches[i]) > 0 and not (len(branches[i]) == 1 and random.random() < 0.5) else 'NULL'
branch_vars.append(branch_var)
if i == 0:
fast += '''
Block *b%d = new Block("%s", %s);
''' % (i, entry, branch_var)
else:
fast += ''' Block *b%d = new Block("print(%d); state = check(); modded = state %% %d; %s", %s);
''' % (i, i, len(branches[i])+1, '// ' + ('.' * int(random.expovariate(0.5/num))), branch_var)
for i in range(num):
branch_var = branch_vars[i]
b = branches[i]
for j in range(len(b)):
if branch_var == 'NULL':
fast += ''' b%d->AddBranchTo(b%d, "modded == %d");
''' % (i, b[j], j)
else:
fast += ''' b%d->AddBranchTo(b%d, "case %d:");
''' % (i, b[j], j)
fast += ''' b%d->AddBranchTo(b%d, NULL);
''' % (i, defaults[i])
fast += '''
Relooper r;
'''
for i in range(num):
fast += ''' r.AddBlock(b%d);
''' % i
fast += '''
r.Calculate(b0);
printf("\\n\\n");
r.Render();
puts(buffer);
return 1;
}
'''
slow += '}'
open('fuzz.slow.js', 'w').write(slow)
open('fuzz.cpp', 'w').write(fast)
print '_'
slow_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.slow.js'], stdout=subprocess.PIPE).communicate()[0]
print '.'
subprocess.call(['g++', 'fuzz.cpp', 'Relooper.o', '-o', 'fuzz', '-g'])
print '*'
subprocess.call(['./fuzz'], stdout=open('fuzz.fast.js', 'w'))
print '-'
fast_out = subprocess.Popen(['mozjs', '-m', '-n', 'fuzz.fast.js'], stdout=subprocess.PIPE).communicate()[0]
print
if slow_out != fast_out:
print ''.join([a.rstrip()+'\n' for a in difflib.unified_diff(slow_out.split('\n'), fast_out.split('\n'), fromfile='slow', tofile='fast')])
assert False
#break
|