1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "fuzz-tests/tests.h"
8
9 #include <stdio.h>
10
11 #include "js/AllocPolicy.h"
12 #include "js/Initialization.h"
13 #include "js/RootingAPI.h"
14 #include "vm/JSContext.h"
15
16 #ifdef LIBFUZZER
17 # include "FuzzerDefs.h"
18 #endif
19
20 using namespace mozilla;
21
22 JS::PersistentRootedObject gGlobal;
23 JSContext* gCx = nullptr;
24
getGlobalClass()25 static const JSClass* getGlobalClass() {
26 static const JSClass c = {"global", JSCLASS_GLOBAL_FLAGS,
27 &JS::DefaultGlobalClassOps};
28 return &c;
29 }
30
jsfuzz_createGlobal(JSContext * cx,JSPrincipals * principals)31 static JSObject* jsfuzz_createGlobal(JSContext* cx, JSPrincipals* principals) {
32 /* Create the global object. */
33 JS::RealmOptions options;
34 options.creationOptions().setStreamsEnabled(true).setWeakRefsEnabled(
35 JS::WeakRefSpecifier::EnabledWithCleanupSome);
36 return JS_NewGlobalObject(cx, getGlobalClass(), principals,
37 JS::FireOnNewGlobalHook, options);
38 }
39
jsfuzz_init(JSContext ** cx,JS::PersistentRootedObject * global)40 static bool jsfuzz_init(JSContext** cx, JS::PersistentRootedObject* global) {
41 *cx = JS_NewContext(8L * 1024 * 1024);
42 if (!*cx) {
43 return false;
44 }
45
46 const size_t MAX_STACK_SIZE = 500000;
47
48 JS_SetNativeStackQuota(*cx, MAX_STACK_SIZE);
49
50 js::UseInternalJobQueues(*cx);
51 if (!JS::InitSelfHostedCode(*cx)) {
52 return false;
53 }
54 global->init(*cx);
55 *global = jsfuzz_createGlobal(*cx, nullptr);
56 if (!*global) {
57 return false;
58 }
59 JS::EnterRealm(*cx, *global);
60 return true;
61 }
62
jsfuzz_uninit(JSContext * cx)63 static void jsfuzz_uninit(JSContext* cx) {
64 if (cx) {
65 JS::LeaveRealm(cx, nullptr);
66 JS_DestroyContext(cx);
67 cx = nullptr;
68 }
69 }
70
main(int argc,char * argv[])71 int main(int argc, char* argv[]) {
72 if (!JS_Init()) {
73 fprintf(stderr, "Error: Call to jsfuzz_init() failed\n");
74 return 1;
75 }
76
77 if (!jsfuzz_init(&gCx, &gGlobal)) {
78 fprintf(stderr, "Error: Call to jsfuzz_init() failed\n");
79 return 1;
80 }
81
82 const char* fuzzerEnv = getenv("FUZZER");
83 if (!fuzzerEnv) {
84 fprintf(stderr,
85 "Must specify fuzzing target in FUZZER environment variable\n");
86 return 1;
87 }
88
89 std::string moduleNameStr(getenv("FUZZER"));
90
91 FuzzerFunctions funcs =
92 FuzzerRegistry::getInstance().getModuleFunctions(moduleNameStr);
93 FuzzerInitFunc initFunc = funcs.first;
94 FuzzerTestingFunc testingFunc = funcs.second;
95 if (initFunc) {
96 int ret = initFunc(&argc, &argv);
97 if (ret) {
98 fprintf(stderr, "Fuzzing Interface: Error: Initialize callback failed\n");
99 return ret;
100 }
101 }
102
103 if (!testingFunc) {
104 fprintf(stderr, "Fuzzing Interface: Error: No testing callback found\n");
105 return 1;
106 }
107
108 #ifdef LIBFUZZER
109 fuzzer::FuzzerDriver(&argc, &argv, testingFunc);
110 #elif __AFL_COMPILER
111 testingFunc(nullptr, 0);
112 #endif
113
114 jsfuzz_uninit(gCx);
115
116 JS_ShutDown();
117
118 return 0;
119 }
120