]>
git.proxmox.com Git - rustc.git/blob - src/binaryen/scripts/fuzz_relooper.py
3 # Copyright 2016 WebAssembly Community Group participants
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
18 This fuzzes the relooper using the C API.
26 if os
.environ
.get('LD_LIBRARY_PATH'):
27 os
.environ
['LD_LIBRARY_PATH'] += os
.pathsep
+ 'lib'
29 os
.environ
['LD_LIBRARY_PATH'] = 'lib'
35 num
= random
.randint(2, 250)
36 density
= random
.random() * random
.random()
37 max_decision
= num
* 20
38 decisions
= [random
.randint(1, max_decision
) for x
in range(num
* 3)]
43 bs
= random
.randint(1, max(1,
44 round(density
* random
.random() * (num
- 1))))
46 b
.add(random
.randint(1, num
- 1))
48 defaults
[i
] = random
.choice(b
)
51 optimize
= random
.random() < 0.5
52 print counter
, ':', num
, density
, optimize
55 for temp
in ['fuzz.wasm', 'fuzz.wast', 'fast.txt', 'fuzz.slow.js',
69 if (index == decisions.length) throw 'HALT';
70 console.log('(i32.const ' + (-decisions[index]) + ')');
71 return decisions[index++];
76 slow
+= 'label = 0;\n'
79 while(1) switch(label) {
87 #include "binaryen-c.h"
89 // globals: address 4 is index
90 // decisions are at address 8+
93 BinaryenModuleRef module = BinaryenModuleCreate();
98 BinaryenExpressionRef halter = BinaryenIf(module,
99 BinaryenBinary(module,
101 BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(),
102 BinaryenConst(module, BinaryenLiteralInt32(4))),
103 BinaryenConst(module, BinaryenLiteralInt32(4 * %d)) // jumps of 4 bytes
105 BinaryenUnreachable(module),
109 BinaryenExpressionRef incer = BinaryenStore(module,
111 BinaryenConst(module, BinaryenLiteralInt32(4)),
112 BinaryenBinary(module,
114 BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(),
115 BinaryenConst(module, BinaryenLiteralInt32(4))),
116 BinaryenConst(module, BinaryenLiteralInt32(4))
121 // optionally, print the return value
122 BinaryenExpressionRef args[] = {
123 BinaryenBinary(module,
125 BinaryenConst(module, BinaryenLiteralInt32(0)),
127 4, 0, 4, 0, BinaryenInt32(),
128 BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(),
129 BinaryenConst(module, BinaryenLiteralInt32(4)))
133 BinaryenExpressionRef debugger;
134 if (1) debugger = BinaryenCallImport(module, "print", args, 1,
136 else debugger = BinaryenNop(module);
138 // return the decision. need to subtract 4 that we just added,
139 // and add 8 since that's where we start, so overall offset 4
140 BinaryenExpressionRef returner = BinaryenLoad(module,
141 4, 0, 4, 0, BinaryenInt32(),
142 BinaryenLoad(module, 4, 0, 0, 0, BinaryenInt32(),
143 BinaryenConst(module, BinaryenLiteralInt32(4)))
145 BinaryenExpressionRef checkBodyList[] = { halter, incer, debugger,
147 BinaryenExpressionRef checkBody = BinaryenBlock(module,
148 NULL, checkBodyList, sizeof(checkBodyList) / sizeof(BinaryenExpressionRef)
150 BinaryenFunctionTypeRef i = BinaryenAddFunctionType(module, "i",
153 BinaryenAddFunction(module, "check", i, NULL, 0, checkBody);
155 // contents of main() begin here
157 RelooperRef relooper = RelooperCreate();
161 for i
in range(0, num
):
162 slow
+= ' case %d: console.log("(i32.const %d)"); state = check(); \n' % (
165 for j
in range(len(b
)):
166 slow
+= ' if (state %% %d == %d) { label = %d; break }\n' % (
167 len(b
) + 1, j
, b
[j
]) # TODO: split range 1-n into these options
168 slow
+= ' label = %d; break\n' % defaults
[i
]
170 use_switch
= [random
.random() < 0.5 for i
in range(num
)]
174 RelooperBlockRef b%d;
176 BinaryenExpressionRef args[] = {
177 BinaryenConst(module, BinaryenLiteralInt32(%d))
179 BinaryenExpressionRef list[] = {
180 BinaryenCallImport(module, "print", args, 1, BinaryenNone()),
181 BinaryenSetLocal(module, 0, BinaryenCall(module, "check", NULL, 0,
187 b%d = RelooperAddBlockWithSwitch(relooper,
188 BinaryenBlock(module, NULL, list, 2),
189 BinaryenBinary(module,
191 BinaryenGetLocal(module, 0, BinaryenInt32()),
192 BinaryenConst(module, BinaryenLiteralInt32(%d))
195 ''' % (i
, len(branches
[i
]) + 1)
198 b%d = RelooperAddBlock(relooper, BinaryenBlock(module, NULL, list, 2));
206 for j
in range(len(b
)):
209 values
= ','.join([str(x
) for x
in range(random
.randint(len(b
) + 1,
210 max_decision
+ 2)) if x
% total
== j
])
213 BinaryenIndex values[] = { %s };
214 RelooperAddBranchForSwitch(b%d, b%d, values,
215 sizeof(values) / sizeof(BinaryenIndex), NULL);
217 ''' % (values
, i
, b
[j
])
220 RelooperAddBranch(b%d, b%d, BinaryenBinary(module,
222 BinaryenBinary(module,
224 BinaryenGetLocal(module, 0, BinaryenInt32()),
225 BinaryenConst(module, BinaryenLiteralInt32(%d))
227 BinaryenConst(module, BinaryenLiteralInt32(%d))
229 ''' % (i
, b
[j
], len(b
) + 1, j
)
233 RelooperAddBranchForSwitch(b%d, b%d, NULL, 0, NULL);
234 ''' % (i
, defaults
[i
])
237 RelooperAddBranch(b%d, b%d, NULL, NULL);
238 ''' % (i
, defaults
[i
])
241 BinaryenExpressionRef body = RelooperRenderAndDispose(relooper, b0, 1,
244 int decisions[] = { %s };
245 int numDecisions = sizeof(decisions)/sizeof(int);
247 // write out all the decisions, then the body of the function
248 BinaryenExpressionRef full[numDecisions + 1];
252 for (i = 0; i < numDecisions; i++) {
253 full[i] = BinaryenStore(module,
255 BinaryenConst(module, BinaryenLiteralInt32(8 + 4 * i)),
256 BinaryenConst(module, BinaryenLiteralInt32(decisions[i])),
261 full[numDecisions] = body;
262 BinaryenExpressionRef all = BinaryenBlock(module, NULL, full,
265 BinaryenFunctionTypeRef v = BinaryenAddFunctionType(module, "v",
268 // locals: state, free-for-label
269 BinaryenType localTypes[] = { BinaryenInt32(), BinaryenInt32() };
270 BinaryenFunctionRef theMain = BinaryenAddFunction(module, "main", v,
272 BinaryenSetStart(module, theMain);
276 BinaryenType iparams[] = { BinaryenInt32() };
277 BinaryenFunctionTypeRef vi = BinaryenAddFunctionType(module, "vi",
280 BinaryenAddImport(module, "print", "spectest", "print", vi);
283 BinaryenSetMemory(module, 1, 1, "mem", NULL, NULL, NULL, 0);
285 // optionally, optimize
286 if (%d) BinaryenModuleOptimize(module);
288 assert(BinaryenModuleValidate(module));
292 BinaryenModulePrint(module);
294 BinaryenModuleDispose(module);
298 ''' % (', '.join(map(str, decisions
)), optimize
)
302 open('fuzz.slow.js', 'w').write(slow
)
303 open('fuzz.c', 'w').write(fast
)
306 cmd
= [os
.environ
.get('CC') or 'gcc', 'fuzz.c', '-Isrc',
307 '-lbinaryen', '-lasmjs',
308 '-lsupport', '-Llib/.', '-pthread', '-o', 'fuzz']
309 subprocess
.check_call(cmd
)
311 subprocess
.check_call(['./fuzz'], stdout
=open('fuzz.wast', 'w'))
313 fast_out
= subprocess
.Popen(['bin/wasm-shell', 'fuzz.wast'],
314 stdout
=subprocess
.PIPE
,
315 stderr
=subprocess
.PIPE
).communicate()[0]
317 slow_out
= subprocess
.Popen(['nodejs', 'fuzz.slow.js'],
318 stdout
=subprocess
.PIPE
,
319 stderr
=subprocess
.PIPE
).communicate()[0]
322 if slow_out
!= fast_out
:
323 print ''.join([a
.rstrip() + '\n' for a
in difflib
.unified_diff(
324 slow_out
.split('\n'),
325 fast_out
.split('\n'),