OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 // Random-walk fuzzer for the Dart VM. | 5 // Random-walk fuzzer for the Dart VM. |
6 // | 6 // |
7 // Start with all the classes and libraries and various interesting values. | 7 // Start with all the classes and libraries and various interesting values. |
8 // Repeatedly choose one as a receiver, construct a message it is likely to | 8 // Repeatedly choose one as a receiver, construct a message it is likely to |
9 // understand, send the message, and add the result. | 9 // understand, send the message, and add the result. |
10 // | 10 // |
(...skipping 29 matching lines...) Expand all Loading... |
40 // When running on many machines in parallel, the current time alone | 40 // When running on many machines in parallel, the current time alone |
41 // is a poor choice of seed. | 41 // is a poor choice of seed. |
42 seed = 0; | 42 seed = 0; |
43 try { | 43 try { |
44 var f = new File("/dev/urandom").openSync(); | 44 var f = new File("/dev/urandom").openSync(); |
45 seed = (seed << 8) | f.readByteSync(); | 45 seed = (seed << 8) | f.readByteSync(); |
46 seed = (seed << 8) | f.readByteSync(); | 46 seed = (seed << 8) | f.readByteSync(); |
47 seed = (seed << 8) | f.readByteSync(); | 47 seed = (seed << 8) | f.readByteSync(); |
48 seed = (seed << 8) | f.readByteSync(); | 48 seed = (seed << 8) | f.readByteSync(); |
49 f.close(); | 49 f.close(); |
50 } catch (e) { | 50 } catch(e) { |
51 print("Failed to read from /dev/urandom: $e"); | 51 print("Failed to read from /dev/urandom: $e"); |
52 } | 52 } |
53 | 53 |
54 seed ^= new DateTime.now().millisecondsSinceEpoch; | 54 seed ^= new DateTime.now().millisecondsSinceEpoch; |
55 seed &= 0xFFFFFFFF; | 55 seed &= 0xFFFFFFFF; |
56 } | 56 } |
57 random = new Random(seed); | 57 random = new Random(seed); |
58 | 58 |
59 // Information needed to reproduce this run. | 59 // Information needed to reproduce this run. |
60 print("Dart VM fuzzer"); | 60 print("Dart VM fuzzer"); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 List<Candidate<ObjectMirror>> candidateReceivers = | 101 List<Candidate<ObjectMirror>> candidateReceivers = |
102 new List<Candidate<ObjectMirror>>(); | 102 new List<Candidate<ObjectMirror>>(); |
103 List<Candidate<InstanceMirror>> candidateArguments = | 103 List<Candidate<InstanceMirror>> candidateArguments = |
104 new List<Candidate<InstanceMirror>>(); | 104 new List<Candidate<InstanceMirror>>(); |
105 | 105 |
106 void addInstance(var instance) { | 106 void addInstance(var instance) { |
107 addInstanceMirror(reflect(instance)); | 107 addInstanceMirror(reflect(instance)); |
108 } | 108 } |
109 | 109 |
110 void addInstanceMirror(InstanceMirror mirror, | 110 void addInstanceMirror(InstanceMirror mirror, |
111 [Candidate origin, String message]) { | 111 [Candidate origin, String message]) { |
112 var c = new Candidate<InstanceMirror>(); | 112 var c = new Candidate<InstanceMirror>(); |
113 c.mirror = mirror; | 113 c.mirror = mirror; |
114 c.origin = origin; | 114 c.origin = origin; |
115 c.message = message; | 115 c.message = message; |
116 | 116 |
117 candidateReceivers.add(c); | 117 candidateReceivers.add(c); |
118 candidateArguments.add(c); | 118 candidateArguments.add(c); |
119 } | 119 } |
120 | 120 |
121 void addObjectMirror(ObjectMirror mirror) { | 121 void addObjectMirror(ObjectMirror mirror) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 addInstance(-1.0); | 163 addInstance(-1.0); |
164 addInstance(0.0); | 164 addInstance(0.0); |
165 addInstance(1.0); | 165 addInstance(1.0); |
166 addInstance(2.0); | 166 addInstance(2.0); |
167 addInstance(double.NAN); | 167 addInstance(double.NAN); |
168 addInstance(double.INFINITY); | 168 addInstance(double.INFINITY); |
169 addInstance(double.NEGATIVE_INFINITY); | 169 addInstance(double.NEGATIVE_INFINITY); |
170 addInstance(double.MIN_POSITIVE); | 170 addInstance(double.MIN_POSITIVE); |
171 addInstance(double.MAX_FINITE); | 171 addInstance(double.MAX_FINITE); |
172 | 172 |
173 addInstance("foo"); // ASCII string | 173 addInstance("foo"); // ASCII string |
174 addInstance("blåbærgrød"); // Latin1 string | 174 addInstance("blåbærgrød"); // Latin1 string |
175 addInstance("Îñţérñåţîöñåļîžåţîờñ"); // Unicode string | 175 addInstance("Îñţérñåţîöñåļîžåţîờñ"); // Unicode string |
176 addInstance("𝄞"); // Surrogate pairs | 176 addInstance("𝄞"); // Surrogate pairs |
177 addInstance("𝄞"[0]); // Surrogate pairs | 177 addInstance("𝄞"[0]); // Surrogate pairs |
178 addInstance("𝄞"[1]); // Surrogate pairs | 178 addInstance("𝄞"[1]); // Surrogate pairs |
179 addInstance("\u{0}"); // Non-printing charater | 179 addInstance("\u{0}"); // Non-printing charater |
180 addInstance("\u{1}"); // Non-printing charater | 180 addInstance("\u{1}"); // Non-printing charater |
181 addInstance("f\u{0}oo"); // Internal NUL | 181 addInstance("f\u{0}oo"); // Internal NUL |
182 addInstance("blåbæ\u{0}rgrød"); // Internal NUL | 182 addInstance("blåbæ\u{0}rgrød"); // Internal NUL |
183 addInstance("Îñţérñåţîö\u{0}ñåļîžåţîờñ"); // Internal NUL | 183 addInstance("Îñţérñåţîö\u{0}ñåļîžåţîờñ"); // Internal NUL |
184 addInstance("\u{0}𝄞"); // Internal NUL | 184 addInstance("\u{0}𝄞"); // Internal NUL |
185 | 185 |
186 for (int len = 0; len < 8; len++) { | 186 for (int len = 0; len < 8; len++) { |
187 addInstance(fillInt(new Int8List(len))); | 187 addInstance(fillInt(new Int8List(len))); |
188 addInstance(fillInt(new Int16List(len))); | 188 addInstance(fillInt(new Int16List(len))); |
189 addInstance(fillInt(new Int32List(len))); | 189 addInstance(fillInt(new Int32List(len))); |
190 addInstance(fillInt(new Int64List(len))); | 190 addInstance(fillInt(new Int64List(len))); |
191 addInstance(fillInt(new Uint8List(len))); | 191 addInstance(fillInt(new Uint8List(len))); |
192 addInstance(fillInt(new Uint16List(len))); | 192 addInstance(fillInt(new Uint16List(len))); |
193 addInstance(fillInt(new Uint32List(len))); | 193 addInstance(fillInt(new Uint32List(len))); |
194 addInstance(fillInt(new Uint64List(len))); | 194 addInstance(fillInt(new Uint64List(len))); |
195 addInstance(fillFloat(new Float32List(len))); | 195 addInstance(fillFloat(new Float32List(len))); |
196 addInstance(fillFloat(new Float64List(len))); | 196 addInstance(fillFloat(new Float64List(len))); |
197 } | 197 } |
198 | 198 |
199 randomInstance(ignore) { | 199 randomInstance(ignore) { |
200 return randomElementOf(candidateArguments).mirror.reflectee; | 200 return randomElementOf(candidateArguments).mirror.reflectee; |
201 } | 201 } |
202 | |
203 for (int len = 0; len < 8; len++) { | 202 for (int len = 0; len < 8; len++) { |
204 addInstance(new List.generate(len, randomInstance)); | 203 addInstance(new List.generate(len, randomInstance)); |
205 } | 204 } |
206 } | 205 } |
207 | 206 |
208 void fillInt(TypedData d) { | 207 void fillInt(TypedData d) { |
209 for (var i = 0; i < d.length; i++) { | 208 for (var i = 0; i < d.length; i++) { |
210 d[i] = random.nextInt(0xFFFFFFFF); | 209 d[i] = random.nextInt(0xFFFFFFFF); |
211 } | 210 } |
212 } | 211 } |
213 | 212 |
214 void fillFloat(TypedData d) { | 213 void fillFloat(TypedData d) { |
215 for (var i = 0; i < d.length; i++) { | 214 for (var i = 0; i < d.length; i++) { |
216 d[i] = random.nextDouble(); | 215 d[i] = random.nextDouble(); |
217 } | 216 } |
218 } | 217 } |
219 | 218 |
220 void setupClasses() { | 219 void setupClasses() { |
221 currentMirrorSystem().libraries.values.forEach((lib) { | 220 currentMirrorSystem().libraries.values.forEach((lib) { |
222 if (lib.simpleName == #fuzzer) return; // Don't recurse. | 221 if (lib.simpleName == #fuzzer) return; // Don't recurse. |
223 addObjectMirror(lib); | 222 addObjectMirror(lib); |
224 lib.declarations.values.forEach((decl) { | 223 lib.declarations.values.forEach((decl) { |
225 if (decl is ClassMirror) { | 224 if (decl is ClassMirror) { |
226 addObjectMirror(decl); | 225 addObjectMirror(decl); |
227 } | 226 } |
228 }); | 227 }); |
229 }); | 228 }); |
230 } | 229 } |
231 | 230 |
232 MethodMirror randomMethodOf(receiver) { | 231 MethodMirror randomMethodOf(receiver) { |
233 if (receiver is ClassMirror) { | 232 if (receiver is ClassMirror) { |
234 return randomElementOf(receiver.declarations.values | 233 return randomElementOf(receiver.declarations.values.where( |
235 .where((d) => d is MethodMirror && d.isStatic) | 234 (d) => d is MethodMirror && d.isStatic).toList()); |
236 .toList()); | |
237 } else if (receiver is LibraryMirror) { | 235 } else if (receiver is LibraryMirror) { |
238 return randomElementOf( | 236 return randomElementOf(receiver.declarations.values.where( |
239 receiver.declarations.values.where((d) => d is MethodMirror).toList()); | 237 (d) => d is MethodMirror).toList()); |
240 } else if (receiver is InstanceMirror) { | 238 } else if (receiver is InstanceMirror) { |
241 var methods = []; | 239 var methods = []; |
242 var cls = receiver.type; | 240 var cls = receiver.type; |
243 while (cls != reflectClass(Object)) { | 241 while (cls != reflectClass(Object)) { |
244 cls.declarations.values.forEach((d) { | 242 cls.declarations.values.forEach((d) { |
245 if (d is MethodMirror && !d.isStatic) methods.add(d); | 243 if (d is MethodMirror && !d.isStatic) methods.add(d); |
246 }); | 244 }); |
247 cls = cls.superclass; | 245 cls = cls.superclass; |
248 } | 246 } |
249 return randomElementOf(methods); | 247 return randomElementOf(methods); |
(...skipping 28 matching lines...) Expand all Loading... |
278 | 276 |
279 String message = prettyMessageName(receiver, method); | 277 String message = prettyMessageName(receiver, method); |
280 if (trace) { | 278 if (trace) { |
281 c.trace(); | 279 c.trace(); |
282 print(message); | 280 print(message); |
283 } | 281 } |
284 | 282 |
285 if (method.isConstructor) { | 283 if (method.isConstructor) { |
286 try { | 284 try { |
287 result = receiver.newInstance(method.simpleName, positional, named); | 285 result = receiver.newInstance(method.simpleName, positional, named); |
288 } catch (e) {} | 286 } catch(e) {} |
289 } else if (method.isRegularMethod) { | 287 } else if (method.isRegularMethod) { |
290 try { | 288 try { |
291 result = receiver.invoke(method.simpleName, positional, named); | 289 result = receiver.invoke(method.simpleName, positional, named); |
292 } catch (e) {} | 290 } catch(e) {} |
293 } else if (method.isGetter) { | 291 } else if (method.isGetter) { |
294 try { | 292 try { |
295 result = receiver.getField(method.simpleName); | 293 result = receiver.getField(method.simpleName); |
296 } catch (e) {} | 294 } catch(e) {} |
297 } else if (method.isSetter) { | 295 } else if (method.isSetter) { |
298 try { | 296 try { |
299 result = receiver.setField(method.simpleName, positional[0]); | 297 result = receiver.setField(method.simpleName, positional[0]); |
300 } catch (e) {} | 298 } catch(e) {} |
301 } | 299 } |
302 | 300 |
303 if (result != null) { | 301 if (result != null) { |
304 addInstanceMirror(result, c, message); | 302 addInstanceMirror(result, c, message); |
305 } | 303 } |
306 } | 304 } |
307 | 305 |
308 InstanceMirror randomArgumentWithBias(TypeMirror bias) { | 306 InstanceMirror randomArgumentWithBias(TypeMirror bias) { |
309 if (maybe(0.75)) { | 307 if (maybe(0.75)) { |
310 for (var candidate in candidateArguments) { | 308 for (var candidate in candidateArguments) { |
(...skipping 23 matching lines...) Expand all Loading... |
334 if (p.isNamed && maybe(0.5)) { | 332 if (p.isNamed && maybe(0.5)) { |
335 result[p.simpleName] = randomArgumentWithBias(p.type); | 333 result[p.simpleName] = randomArgumentWithBias(p.type); |
336 } | 334 } |
337 } | 335 } |
338 | 336 |
339 return result; | 337 return result; |
340 } | 338 } |
341 | 339 |
342 void garbageCollect() { | 340 void garbageCollect() { |
343 // Chain a bunch of moderately sized arrays, then let go of them. Using a | 341 // Chain a bunch of moderately sized arrays, then let go of them. Using a |
344 // moderate size avoids our allocations going directly to a large object | 342 // moderate size avoids our allocations going directly to a large object |
345 // page in old space. | 343 // page in old space. |
346 var n; | 344 var n; |
347 for (int i = 0; i < 2048; i++) { | 345 for (int i = 0; i < 2048; i++) { |
348 var m = new List(512); | 346 var m = new List(512); |
349 m[0] = n; | 347 m[0] = n; |
350 n = m; | 348 n = m; |
351 } | 349 } |
352 } | 350 } |
OLD | NEW |