mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:30:32 +00:00
af50ee90f6
After investigation, we've decided to just leave this class out of fuzzing, since it's a private class. Bug: https://github.com/dart-lang/sdk/issues/53350 Change-Id: I208fe4d81e9c0245955aa241e1f1643a21274cff Fixes: https://github.com/dart-lang/sdk/issues/53350 TEST=No code changes Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/323100 Auto-Submit: Liam Appelbe <liama@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
199 lines
5.3 KiB
Dart
199 lines
5.3 KiB
Dart
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// This test reflectively enumerates all the methods in the system and tries to
|
|
// invoke them with various basic values (nulls, ints, etc). This may result in
|
|
// Dart exceptions or hangs, but should never result in crashes or JavaScript
|
|
// exceptions.
|
|
|
|
library test.invoke_natives;
|
|
|
|
import 'dart:mirrors';
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
// Methods to be skipped, by qualified name.
|
|
var denylist = [
|
|
// Don't recurse on this test.
|
|
'test.invoke_natives',
|
|
|
|
// Don't exit the test pre-maturely.
|
|
'dart.io.exit',
|
|
'dart.isolate.Isolate.exit',
|
|
|
|
// Don't change the exit code, which may fool the test harness.
|
|
'dart.io.exitCode',
|
|
|
|
// Don't kill random other processes.
|
|
'dart.io.Process.killPid',
|
|
|
|
// Don't break into the debugger.
|
|
'dart.developer.debugger',
|
|
|
|
// Don't run blocking io calls.
|
|
'dart.io.sleep',
|
|
new RegExp(r".*Sync$"),
|
|
|
|
// Don't call private methods in dart.async as they may circumvent the zoned
|
|
// error handling below.
|
|
new RegExp(r"^dart\.async\._.*$"),
|
|
|
|
// Don't try to invoke FFI Natives on simulator.
|
|
// TODO(http://dartbug.com/48365): Support FFI in simulators.
|
|
'dart._internal.FinalizerEntry.setExternalSize',
|
|
|
|
// Don't instantiate structs with bogus memory.
|
|
'dart.ffi._AsTypedListFinalizerData',
|
|
|
|
// Don't instantiate callables with random function pointers.
|
|
'dart.ffi._NativeCallableIsolateLocal',
|
|
];
|
|
|
|
bool isDenylisted(Symbol qualifiedSymbol) {
|
|
var qualifiedString = MirrorSystem.getName(qualifiedSymbol);
|
|
for (var pattern in denylist) {
|
|
if (qualifiedString.contains(pattern)) {
|
|
print('Skipping $qualifiedString');
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
class Task {
|
|
dynamic name;
|
|
dynamic action;
|
|
}
|
|
|
|
var queue = <Task>[];
|
|
|
|
checkMethod(MethodMirror m, ObjectMirror target, [origin]) {
|
|
if (isDenylisted(m.qualifiedName)) return;
|
|
|
|
var task = new Task();
|
|
task.name = '${MirrorSystem.getName(m.qualifiedName)} from $origin';
|
|
|
|
if (m.isRegularMethod) {
|
|
task.action = () => target.invoke(
|
|
m.simpleName, new List.filled(m.parameters.length, fuzzArgument));
|
|
} else if (m.isGetter) {
|
|
task.action = () => target.getField(m.simpleName);
|
|
} else if (m.isSetter) {
|
|
task.action = () => target.setField(m.simpleName, null);
|
|
} else if (m.isConstructor) {
|
|
return;
|
|
} else {
|
|
throw "Unexpected method kind";
|
|
}
|
|
|
|
queue.add(task);
|
|
}
|
|
|
|
checkInstance(instanceMirror, origin) {
|
|
ClassMirror? klass = instanceMirror.type;
|
|
while (klass != null) {
|
|
instanceMirror.type.declarations.values
|
|
.where((d) => d is MethodMirror && !d.isStatic)
|
|
.forEach((m) => checkMethod(m, instanceMirror, origin));
|
|
klass = klass.superclass;
|
|
}
|
|
}
|
|
|
|
checkClass(classMirror) {
|
|
classMirror.declarations.values
|
|
.where((d) => d is MethodMirror && d.isStatic)
|
|
.forEach((m) => checkMethod(m, classMirror));
|
|
|
|
classMirror.declarations.values
|
|
.where((d) => d is MethodMirror && d.isConstructor)
|
|
.forEach((m) {
|
|
if (isDenylisted(m.qualifiedName)) return;
|
|
var task = new Task();
|
|
task.name = MirrorSystem.getName(m.qualifiedName);
|
|
|
|
task.action = () {
|
|
var instance = classMirror.newInstance(m.constructorName,
|
|
new List.filled(m.parameters.length, fuzzArgument));
|
|
checkInstance(instance, task.name);
|
|
};
|
|
queue.add(task);
|
|
});
|
|
}
|
|
|
|
checkLibrary(libraryMirror) {
|
|
print(libraryMirror.simpleName);
|
|
if (isDenylisted(libraryMirror.qualifiedName)) return;
|
|
|
|
libraryMirror.declarations.values
|
|
.where((d) => d is ClassMirror)
|
|
.forEach(checkClass);
|
|
|
|
libraryMirror.declarations.values
|
|
.where((d) => d is MethodMirror)
|
|
.forEach((m) => checkMethod(m, libraryMirror));
|
|
}
|
|
|
|
var testZone;
|
|
|
|
doOneTask() {
|
|
if (queue.length == 0) {
|
|
print('Done');
|
|
// Forcibly exit as we likely opened sockets and timers during the fuzzing.
|
|
exit(0);
|
|
}
|
|
|
|
var task = queue.removeLast();
|
|
print(task.name);
|
|
try {
|
|
task.action();
|
|
} catch (e) {}
|
|
|
|
// Register the next task in a timer callback so as to yield to async code
|
|
// scheduled in the current task. This isn't necessary for the test itself,
|
|
// but is helpful when trying to figure out which function is responsible for
|
|
// a crash.
|
|
testZone.createTimer(Duration.zero, doOneTask);
|
|
}
|
|
|
|
var fuzzArgument;
|
|
|
|
main() {
|
|
fuzzArgument = null;
|
|
fuzzArgument = 1; // //# smi: ok
|
|
fuzzArgument = false; // //# false: ok
|
|
fuzzArgument = 'string'; // //# string: ok
|
|
fuzzArgument = new List.filled(0, null); // //# emptyarray: ok
|
|
|
|
print('Fuzzing with $fuzzArgument');
|
|
|
|
currentMirrorSystem().libraries.values.forEach(checkLibrary);
|
|
|
|
var valueObjects = [
|
|
true,
|
|
false,
|
|
null,
|
|
[],
|
|
{},
|
|
dynamic,
|
|
0,
|
|
0xEFFFFFF,
|
|
0xFFFFFFFF,
|
|
0xFFFFFFFFFFFFFFFF,
|
|
3.14159,
|
|
"foo",
|
|
'blåbærgrød',
|
|
'Îñţérñåţîöñåļîžåţîờñ',
|
|
"\u{1D11E}",
|
|
#symbol
|
|
];
|
|
valueObjects.forEach((v) => checkInstance(reflect(v), 'value object'));
|
|
|
|
void uncaughtErrorHandler(self, parent, zone, error, stack) {}
|
|
|
|
var zoneSpec =
|
|
new ZoneSpecification(handleUncaughtError: uncaughtErrorHandler);
|
|
testZone = Zone.current.fork(specification: zoneSpec);
|
|
testZone.createTimer(Duration.zero, doOneTask);
|
|
}
|