| 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 |