Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 library fuzzer; | |
| 2 | |
| 3 import 'dart:io'; | |
| 4 import 'dart:math'; | |
| 5 import 'dart:mirrors'; | |
| 6 | |
| 7 void main([List<String> args]) { | |
| 8 int seed; | |
| 9 if (args.length == 1) { | |
| 10 seed = int.parse(args[0]); | |
| 11 } else { | |
| 12 seed = new DateTime.now().millisecondsSinceEpoch & ((1<<31)-1); | |
|
groebert
2015/01/16 09:55:16
If we execute on multiple machines at the same tim
rmacnak
2015/02/05 00:38:28
Added
| |
| 13 } | |
| 14 random = new Random(seed); | |
| 15 | |
| 16 print("Dart VM fuzzer"); | |
| 17 print("Executable: ${Platform.executable}"); | |
| 18 print("Arguments: ${Platform.executableArguments}"); | |
| 19 print("Version: ${Platform.version}"); | |
| 20 print("Seed: ${seed}"); | |
| 21 | |
| 22 setupInterestingValues(); | |
| 23 setupClasses(); | |
| 24 | |
| 25 while(true) { | |
|
groebert
2015/01/16 09:55:16
Better use a pre-defined maximum number of iterati
rmacnak
2015/02/05 00:38:28
Bounded
| |
| 26 fuzz(randomElementOf(candidateReceivers)); | |
| 27 if (maybe(0.01)) garbageCollect(); | |
| 28 } | |
| 29 } | |
| 30 | |
| 31 Random random; | |
| 32 | |
| 33 bool maybe(probability) => random.nextDouble() < probability; | |
| 34 | |
| 35 randomElementOf(list) { | |
| 36 return list.length == 0 ? null : list[random.nextInt(list.length)]; | |
| 37 } | |
| 38 | |
| 39 List<ObjectMirror> candidateReceivers = new List<ObjectMirror>(); | |
| 40 List<InstanceMirror> candidateArguments = new List<InstanceMirror>(); | |
| 41 | |
| 42 void addInstance(var i) { | |
| 43 var mirror = reflect(i); | |
| 44 candidateReceivers.add(mirror); | |
| 45 candidateArguments.add(mirror); | |
| 46 } | |
| 47 | |
| 48 void setupInterestingValues() { | |
| 49 addInstance(null); | |
| 50 addInstance(true); | |
| 51 addInstance(false); | |
| 52 | |
| 53 addInstance([]); | |
| 54 addInstance(const []); | |
| 55 addInstance({}); | |
| 56 addInstance(const {}); | |
| 57 | |
| 58 addInstance(() => null); | |
| 59 | |
| 60 addInstance(-1); | |
| 61 addInstance(0); | |
| 62 addInstance(1); | |
| 63 addInstance(2); | |
| 64 | |
| 65 addInstance(1 << 31); | |
| 66 addInstance(1 << 31 + 1); | |
| 67 addInstance(1 << 31 - 1); | |
| 68 | |
| 69 addInstance(1 << 32); | |
| 70 addInstance(1 << 32 + 1); | |
| 71 addInstance(1 << 32 - 1); | |
| 72 | |
| 73 addInstance(1 << 63); | |
| 74 addInstance(1 << 63 + 1); | |
| 75 addInstance(1 << 63 - 1); | |
| 76 | |
| 77 addInstance(1 << 64); | |
| 78 addInstance(1 << 64 + 1); | |
| 79 addInstance(1 << 64 - 1); | |
| 80 | |
| 81 addInstance(-1.0); | |
| 82 addInstance(0.0); | |
| 83 addInstance(1.0); | |
| 84 addInstance(2.0); | |
| 85 addInstance(double.NAN); | |
| 86 addInstance(double.INFINITY); | |
| 87 addInstance(double.NEGATIVE_INFINITY); | |
| 88 addInstance(double.MIN_POSITIVE); | |
| 89 addInstance(double.MAX_FINITE); | |
| 90 | |
| 91 addInstance("foo"); // ASCII string | |
| 92 addInstance("blåbærgrød"); // Latin1 string | |
| 93 addInstance("Îñţérñåţîöñåļîžåţîờñ"); // Unicode string | |
| 94 addInstance("𝄞"); // Surrogate pairs | |
| 95 addInstance("𝄞"[0]); // Surrogate pairs | |
| 96 addInstance("𝄞"[1]); // Surrogate pairs | |
| 97 addInstance("\u{0}"); // Non-printing charater | |
| 98 addInstance("\u{1}"); // Non-printing charater | |
| 99 addInstance("f\u{0}oo"); // Internal NUL | |
| 100 addInstance("blåbæ\u{0}rgrød"); // Internal NUL | |
| 101 addInstance("Îñţérñåţîö\u{0}ñåļîžåţîờñ"); // Internal NUL | |
| 102 addInstance("\u{0}𝄞"); // Internal NUL | |
| 103 | |
| 104 // TODO: Lists and maps of these values. | |
|
rmacnak
2015/02/05 00:38:28
Implemented.
| |
| 105 // TODO: TypedData. | |
| 106 } | |
| 107 | |
| 108 void setupClasses() { | |
| 109 currentMirrorSystem().libraries.values.forEach((lib) { | |
| 110 candidateReceivers.add(lib); | |
| 111 lib.declarations.values.forEach((decl) { | |
| 112 if (decl is ClassMirror) { | |
| 113 candidateReceivers.add(decl); | |
| 114 } | |
| 115 }); | |
| 116 }); | |
| 117 } | |
| 118 | |
| 119 MethodMirror randomMethodOf(receiver) { | |
| 120 if (receiver is ClassMirror) { | |
| 121 return randomElementOf(receiver.declarations.values.where( | |
| 122 (d) => d is MethodMirror && d.isStatic).toList()); | |
| 123 } else if (receiver is LibraryMirror) { | |
| 124 return randomElementOf(receiver.declarations.values.where( | |
| 125 (d) => d is MethodMirror).toList()); | |
| 126 } else if (receiver is InstanceMirror) { | |
| 127 var methods = []; | |
| 128 var cls = receiver.type; | |
| 129 while (cls != reflectClass(Object)) { | |
| 130 cls.declarations.values.forEach((d) { | |
| 131 if (d is MethodMirror && !d.isStatic) methods.add(d); | |
| 132 }); | |
| 133 cls = cls.superclass; | |
| 134 } | |
| 135 return randomElementOf(methods); | |
| 136 } | |
| 137 throw new Error("UNREACHABLE"); | |
| 138 } | |
| 139 | |
| 140 void fuzz(ObjectMirror receiver) { | |
| 141 MethodMirror method = randomMethodOf(receiver); | |
| 142 if (method == null) return; | |
| 143 List positional = randomPositionalArgumentsFor(method); | |
| 144 Map named = randomNamedArgumentsFor(method); | |
| 145 InstanceMirror result; | |
| 146 | |
| 147 print("$receiver >> ${method.simpleName}"); | |
| 148 | |
| 149 if (method.isConstructor) { | |
|
groebert
2015/01/16 09:55:16
Maybe also add a blacklist of known-bad classes/me
rmacnak
2015/02/05 00:38:28
Excluded the fuzzer itself and a few functions fro
| |
| 150 try { | |
| 151 result = receiver.newInstance(method.simpleName, positional, named); | |
| 152 } catch(e) {} | |
| 153 } else if (method.isRegularMethod) { | |
| 154 try { | |
| 155 result = receiver.invoke(method.simpleName, positional, named); | |
| 156 } catch(e) {} | |
| 157 } else if (method.isGetter) { | |
| 158 try { | |
| 159 result = receiver.getField(method.simpleName); | |
| 160 } catch(e) {} | |
| 161 } else if (method.isSetter) { | |
| 162 try { | |
| 163 result = receiver.setField(method.simpleName, positional[0]); | |
| 164 } catch(e) {} | |
| 165 } | |
| 166 | |
| 167 if (result != null) { | |
| 168 addInstance(result); | |
| 169 } | |
| 170 } | |
| 171 | |
| 172 | |
| 173 InstanceMirror randomArgumentWithBias(TypeMirror bias) { | |
| 174 if (maybe(0.75)) { | |
| 175 for (var candidate in candidateArguments) { | |
| 176 if (candidate.type.isAssignableTo(bias)) { | |
| 177 return candidate; | |
| 178 } | |
| 179 } | |
| 180 } | |
| 181 return randomElementOf(candidateArguments); | |
| 182 } | |
| 183 | |
| 184 List randomPositionalArgumentsFor(MethodMirror method) { | |
| 185 var arity = method.parameters.length; | |
| 186 var args = new List(arity); | |
| 187 for (int i = 0; i < arity; i++) { | |
| 188 args[i] = randomArgumentWithBias(method.parameters[i].type); | |
| 189 } | |
| 190 return args; | |
| 191 } | |
| 192 | |
| 193 Map randomNamedArgumentsFor(MethodMirror method) { | |
| 194 // TODO: Implement. | |
|
rmacnak
2015/02/05 00:38:28
Implemented.
| |
| 195 return null; | |
| 196 } | |
| 197 | |
| 198 void garbageCollect() { | |
| 199 // TODO: Chain a bunch of moderately sized arrays, then let go of them. | |
|
rmacnak
2015/02/05 00:38:28
Implemented.
| |
| 200 } | |
| OLD | NEW |