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 |
202 for (int len = 0; len < 8; len++) { | 203 for (int len = 0; len < 8; len++) { |
203 addInstance(new List.generate(len, randomInstance)); | 204 addInstance(new List.generate(len, randomInstance)); |
204 } | 205 } |
205 } | 206 } |
206 | 207 |
207 void fillInt(TypedData d) { | 208 void fillInt(TypedData d) { |
208 for (var i = 0; i < d.length; i++) { | 209 for (var i = 0; i < d.length; i++) { |
209 d[i] = random.nextInt(0xFFFFFFFF); | 210 d[i] = random.nextInt(0xFFFFFFFF); |
210 } | 211 } |
211 } | 212 } |
212 | 213 |
213 void fillFloat(TypedData d) { | 214 void fillFloat(TypedData d) { |
214 for (var i = 0; i < d.length; i++) { | 215 for (var i = 0; i < d.length; i++) { |
215 d[i] = random.nextDouble(); | 216 d[i] = random.nextDouble(); |
216 } | 217 } |
217 } | 218 } |
218 | 219 |
219 void setupClasses() { | 220 void setupClasses() { |
220 currentMirrorSystem().libraries.values.forEach((lib) { | 221 currentMirrorSystem().libraries.values.forEach((lib) { |
221 if (lib.simpleName == #fuzzer) return; // Don't recurse. | 222 if (lib.simpleName == #fuzzer) return; // Don't recurse. |
222 addObjectMirror(lib); | 223 addObjectMirror(lib); |
223 lib.declarations.values.forEach((decl) { | 224 lib.declarations.values.forEach((decl) { |
224 if (decl is ClassMirror) { | 225 if (decl is ClassMirror) { |
225 addObjectMirror(decl); | 226 addObjectMirror(decl); |
226 } | 227 } |
227 }); | 228 }); |
228 }); | 229 }); |
229 } | 230 } |
230 | 231 |
231 MethodMirror randomMethodOf(receiver) { | 232 MethodMirror randomMethodOf(receiver) { |
232 if (receiver is ClassMirror) { | 233 if (receiver is ClassMirror) { |
233 return randomElementOf(receiver.declarations.values.where( | 234 return randomElementOf(receiver.declarations.values |
234 (d) => d is MethodMirror && d.isStatic).toList()); | 235 .where((d) => d is MethodMirror && d.isStatic) |
| 236 .toList()); |
235 } else if (receiver is LibraryMirror) { | 237 } else if (receiver is LibraryMirror) { |
236 return randomElementOf(receiver.declarations.values.where( | 238 return randomElementOf( |
237 (d) => d is MethodMirror).toList()); | 239 receiver.declarations.values.where((d) => d is MethodMirror).toList()); |
238 } else if (receiver is InstanceMirror) { | 240 } else if (receiver is InstanceMirror) { |
239 var methods = []; | 241 var methods = []; |
240 var cls = receiver.type; | 242 var cls = receiver.type; |
241 while (cls != reflectClass(Object)) { | 243 while (cls != reflectClass(Object)) { |
242 cls.declarations.values.forEach((d) { | 244 cls.declarations.values.forEach((d) { |
243 if (d is MethodMirror && !d.isStatic) methods.add(d); | 245 if (d is MethodMirror && !d.isStatic) methods.add(d); |
244 }); | 246 }); |
245 cls = cls.superclass; | 247 cls = cls.superclass; |
246 } | 248 } |
247 return randomElementOf(methods); | 249 return randomElementOf(methods); |
(...skipping 28 matching lines...) Expand all Loading... |
276 | 278 |
277 String message = prettyMessageName(receiver, method); | 279 String message = prettyMessageName(receiver, method); |
278 if (trace) { | 280 if (trace) { |
279 c.trace(); | 281 c.trace(); |
280 print(message); | 282 print(message); |
281 } | 283 } |
282 | 284 |
283 if (method.isConstructor) { | 285 if (method.isConstructor) { |
284 try { | 286 try { |
285 result = receiver.newInstance(method.simpleName, positional, named); | 287 result = receiver.newInstance(method.simpleName, positional, named); |
286 } catch(e) {} | 288 } catch (e) {} |
287 } else if (method.isRegularMethod) { | 289 } else if (method.isRegularMethod) { |
288 try { | 290 try { |
289 result = receiver.invoke(method.simpleName, positional, named); | 291 result = receiver.invoke(method.simpleName, positional, named); |
290 } catch(e) {} | 292 } catch (e) {} |
291 } else if (method.isGetter) { | 293 } else if (method.isGetter) { |
292 try { | 294 try { |
293 result = receiver.getField(method.simpleName); | 295 result = receiver.getField(method.simpleName); |
294 } catch(e) {} | 296 } catch (e) {} |
295 } else if (method.isSetter) { | 297 } else if (method.isSetter) { |
296 try { | 298 try { |
297 result = receiver.setField(method.simpleName, positional[0]); | 299 result = receiver.setField(method.simpleName, positional[0]); |
298 } catch(e) {} | 300 } catch (e) {} |
299 } | 301 } |
300 | 302 |
301 if (result != null) { | 303 if (result != null) { |
302 addInstanceMirror(result, c, message); | 304 addInstanceMirror(result, c, message); |
303 } | 305 } |
304 } | 306 } |
305 | 307 |
306 InstanceMirror randomArgumentWithBias(TypeMirror bias) { | 308 InstanceMirror randomArgumentWithBias(TypeMirror bias) { |
307 if (maybe(0.75)) { | 309 if (maybe(0.75)) { |
308 for (var candidate in candidateArguments) { | 310 for (var candidate in candidateArguments) { |
(...skipping 23 matching lines...) Expand all Loading... |
332 if (p.isNamed && maybe(0.5)) { | 334 if (p.isNamed && maybe(0.5)) { |
333 result[p.simpleName] = randomArgumentWithBias(p.type); | 335 result[p.simpleName] = randomArgumentWithBias(p.type); |
334 } | 336 } |
335 } | 337 } |
336 | 338 |
337 return result; | 339 return result; |
338 } | 340 } |
339 | 341 |
340 void garbageCollect() { | 342 void garbageCollect() { |
341 // Chain a bunch of moderately sized arrays, then let go of them. Using a | 343 // Chain a bunch of moderately sized arrays, then let go of them. Using a |
342 // moderate size avoids our allocations going directly to a large object | 344 // moderate size avoids our allocations going directly to a large object |
343 // page in old space. | 345 // page in old space. |
344 var n; | 346 var n; |
345 for (int i = 0; i < 2048; i++) { | 347 for (int i = 0; i < 2048; i++) { |
346 var m = new List(512); | 348 var m = new List(512); |
347 m[0] = n; | 349 m[0] = n; |
348 n = m; | 350 n = m; |
349 } | 351 } |
350 } | 352 } |
OLD | NEW |