Bug 1247247 - Add AFL-style wasmLoop function for persistent fuzzing. r=luke
authorChristian Holler <choller@mozilla.com>
Thu, 11 Feb 2016 14:55:53 +0100
changeset 284041 54f291017f6382a200f20cd7be9f3ef660df5e81
parent 284040 acaeaa89ffc186aff44994e3b62568f57b68470f
child 284042 e39c9c48355d02dc5e25561477d7f97b6761a154
push id29995
push usercbook@mozilla.com
push dateFri, 12 Feb 2016 14:16:12 +0000
treeherdermozilla-central@218d16a9ddcc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1247247
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1247247 - Add AFL-style wasmLoop function for persistent fuzzing. r=luke MozReview-Commit-ID: RFQ5pqCvl6
js/src/shell/OSObject.cpp
js/src/shell/OSObject.h
js/src/shell/js.cpp
--- a/js/src/shell/OSObject.cpp
+++ b/js/src/shell/OSObject.cpp
@@ -142,17 +142,17 @@ ResolvePath(JSContext* cx, HandleString 
     buffer[len] = '/';
     strncpy(buffer + len + 1, filename.ptr(), sizeof(buffer) - (len+1));
     if (buffer[PATH_MAX] != '\0')
         return nullptr;
 
     return JS_NewStringCopyZ(cx, buffer);
 }
 
-static JSObject*
+JSObject*
 FileAsTypedArray(JSContext* cx, const char* pathname)
 {
     FILE* file = fopen(pathname, "rb");
     if (!file) {
         JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
         return nullptr;
     }
     AutoCloseFile autoClose(file);
--- a/js/src/shell/OSObject.h
+++ b/js/src/shell/OSObject.h
@@ -21,12 +21,15 @@ DefineOS(JSContext* cx, JS::HandleObject
 enum PathResolutionMode {
     RootRelative,
     ScriptRelative
 };
 
 JSString*
 ResolvePath(JSContext* cx, JS::HandleString filenameStr, PathResolutionMode resolveMode);
 
+JSObject*
+FileAsTypedArray(JSContext* cx, const char* pathname);
+
 } // namespace shell
 } // namespace js
 
 #endif /* shell_OSObject_h */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -53,16 +53,17 @@
 #include "jstypes.h"
 #include "jsutil.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "jswrapper.h"
 #include "shellmoduleloader.out.h"
 
+#include "asmjs/Wasm.h"
 #include "builtin/ModuleObject.h"
 #include "builtin/TestingFunctions.h"
 #include "frontend/Parser.h"
 #include "gc/GCInternals.h"
 #include "jit/arm/Simulator-arm.h"
 #include "jit/InlinableNatives.h"
 #include "jit/Ion.h"
 #include "jit/JitcodeMap.h"
@@ -4910,16 +4911,72 @@ SetARMHwCapFlags(JSContext* cx, unsigned
 
     jit::ParseARMHwCapFlags(flagsList.ptr());
 #endif
 
     args.rval().setUndefined();
     return true;
 }
 
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+static bool
+WasmLoop(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    RootedObject callee(cx, &args.callee());
+
+    if (args.length() < 1 || args.length() > 2) {
+        ReportUsageError(cx, callee, "Wrong number of arguments");
+        return false;
+    }
+
+    if (!args[0].isString()) {
+        ReportUsageError(cx, callee, "First argument must be a String");
+        return false;
+    }
+
+    RootedObject importObj(cx);
+    if (!args.get(1).isUndefined()) {
+        if (!args.get(1).isObject()) {
+            ReportUsageError(cx, callee, "Second argument, if present, must be an Object");
+            return false;
+        }
+        importObj = &args[1].toObject();
+    }
+
+    RootedString givenPath(cx, args[0].toString());
+    RootedString str(cx, ResolvePath(cx, givenPath, RootRelative));
+    if (!str)
+        return false;
+
+    JSAutoByteString filename(cx, str);
+    if (!filename)
+        return false;
+
+    while (__AFL_LOOP(1000)) {
+        Rooted<JSObject*> ret(cx, FileAsTypedArray(cx, filename.ptr()));
+        if (!ret)
+            return false;
+
+        Rooted<TypedArrayObject*> typedArray(cx, &ret->as<TypedArrayObject>());
+        if (!TypedArrayObject::ensureHasBuffer(cx, typedArray))
+            return false;
+
+        Rooted<ArrayBufferObject*> arrayBuffer(cx, typedArray->bufferUnshared());
+        RootedObject exportObj(cx);
+        if (!wasm::Eval(cx, arrayBuffer, importObj, &exportObj)) {
+            // Clear any pending exceptions, we don't care about them
+            cx->clearPendingException();
+        }
+    }
+
+    return true;
+}
+#endif // __AFL_HAVE_MANUAL_CONTROL
+
 static const JSFunctionSpecWithHelp shell_functions[] = {
     JS_FN_HELP("version", Version, 0, 0,
 "version([number])",
 "  Get or force a script compilation version number."),
 
     JS_FN_HELP("options", Options, 0, 0,
 "options([option ...])",
 "  Get or toggle JavaScript options."),
@@ -5379,16 +5436,23 @@ TestAssertRecoveredOnBailout,
 "crash([message])",
 "  Crashes the process with a MOZ_CRASH."),
 
     JS_FN_HELP("setARMHwCapFlags", SetARMHwCapFlags, 1, 0,
 "setARMHwCapFlags(\"flag1,flag2 flag3\")",
 "  On non-ARM, no-op. On ARM, set the hardware capabilities. The list of \n"
 "  flags is available by calling this function with \"help\" as the flag's name"),
 
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+    JS_FN_HELP("wasmLoop", WasmLoop, 2, 0,
+"wasmLoop(filename, imports)",
+"  Performs an AFL-style persistent loop reading data from the given file and passing it\n"
+"  to the 'wasmEval' function together with the specified imports object."),
+#endif
+
     JS_FS_HELP_END
 };
 
 static const JSFunctionSpecWithHelp console_functions[] = {
     JS_FN_HELP("log", Print, 0, 0,
 "log([exp ...])",
 "  Evaluate and print expressions to stdout.\n"
 "  This function is an alias of the print() function."),