Skip to content

Commit 01454ca

Browse files
OSS-Fuzz targets improvements (bellard#267)
* Move fuzz target sources from the oss-fuzz repository here * Add support to build libFuzzer targets * Simplify the fuzz_eval and fuzz_compile targets The use of JS_NewContext instead of JS_NewContextRaw spares to call JS_AddIntrinsic<XYZ> functions from the fuzz target, since the public JS_NewContext API does exactly the same. * Simplify the fuzz_regexp target fuzz_regexp doesn't need to be dependant on libquickjs since the runtime and the context - that were provided by libquickjs - were only created to call two simple functions implemented in libquickjs which could be mimicked by the fuzzer. The removal of runtime and context objects implicated further simplifications, like the omission of their one-time creation. Finally, writing the result of the regexp operations into a file is also superfluous, since it's not used by anybody. * Recreate and destroy JS runtime and context in fuzz_eval and fuzz_compile targets Before this patch, the test executions were not independent, since all the executed tests used the same JavaScript runtime and context, causing irreproducible failure reports. * Enable bignumber support in eval and compile targets Big numbers are used by the input corpus, but the targets were not able to interpret them since they were not compiled into them. This change improved the inital coverage of the fuzz_eval target with 21% and the coverage of the fuzz_compile target with 25% when using the official corpus. * Ensure std and os modules are available in the fuzz_eval and fuzz_compile targets * Add fuzzer dictionary with builtin and variable names. Furthermore, added a JS script that collects all the builtin names from the executing engine. * Move common fuzzer code into one place * Enable to define the LIB_FUZZING_ENGINE variable to ease the oss-fuzz integration * Add README to fuzzers
1 parent 0c8feca commit 01454ca

File tree

8 files changed

+553
-1
lines changed

8 files changed

+553
-1
lines changed

Makefile

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ ifdef CONFIG_CLANG
111111
AR=$(CROSS_PREFIX)ar
112112
endif
113113
endif
114+
LIB_FUZZING_ENGINE ?= "-fsanitize=fuzzer"
114115
else ifdef CONFIG_COSMO
115116
CONFIG_LTO=
116117
HOST_CC=gcc
@@ -248,6 +249,17 @@ qjs-debug$(EXE): $(patsubst %.o, %.debug.o, $(QJS_OBJS))
248249
qjsc$(EXE): $(OBJDIR)/qjsc.o $(QJS_LIB_OBJS)
249250
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
250251

252+
fuzz_eval: $(OBJDIR)/fuzz_eval.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a
253+
$(CC) $(CFLAGS_OPT) $^ -o fuzz_eval $(LIB_FUZZING_ENGINE)
254+
255+
fuzz_compile: $(OBJDIR)/fuzz_compile.o $(OBJDIR)/fuzz_common.o libquickjs.fuzz.a
256+
$(CC) $(CFLAGS_OPT) $^ -o fuzz_compile $(LIB_FUZZING_ENGINE)
257+
258+
fuzz_regexp: $(OBJDIR)/fuzz_regexp.o $(OBJDIR)/libregexp.fuzz.o $(OBJDIR)/cutils.fuzz.o $(OBJDIR)/libunicode.fuzz.o
259+
$(CC) $(CFLAGS_OPT) $^ -o fuzz_regexp $(LIB_FUZZING_ENGINE)
260+
261+
libfuzzer: fuzz_eval fuzz_compile fuzz_regexp
262+
251263
ifneq ($(CROSS_PREFIX),)
252264

253265
$(QJSC): $(OBJDIR)/qjsc.host.o \
@@ -289,6 +301,9 @@ libquickjs.a: $(patsubst %.o, %.nolto.o, $(QJS_LIB_OBJS))
289301
$(AR) rcs $@ $^
290302
endif # CONFIG_LTO
291303

304+
libquickjs.fuzz.a: $(patsubst %.o, %.fuzz.o, $(QJS_LIB_OBJS))
305+
$(AR) rcs $@ $^
306+
292307
repl.c: $(QJSC) repl.js
293308
$(QJSC) -c -o $@ -m repl.js
294309

@@ -317,6 +332,9 @@ run-test262-32: $(patsubst %.o, %.m32.o, $(OBJDIR)/run-test262.o $(QJS_LIB_OBJS)
317332
$(OBJDIR)/%.o: %.c | $(OBJDIR)
318333
$(CC) $(CFLAGS_OPT) -c -o $@ $<
319334

335+
$(OBJDIR)/fuzz_%.o: fuzz/fuzz_%.c | $(OBJDIR)
336+
$(CC) $(CFLAGS_OPT) -c -I. -o $@ $<
337+
320338
$(OBJDIR)/%.host.o: %.c | $(OBJDIR)
321339
$(HOST_CC) $(CFLAGS_OPT) -c -o $@ $<
322340

@@ -335,6 +353,9 @@ $(OBJDIR)/%.m32s.o: %.c | $(OBJDIR)
335353
$(OBJDIR)/%.debug.o: %.c | $(OBJDIR)
336354
$(CC) $(CFLAGS_DEBUG) -c -o $@ $<
337355

356+
$(OBJDIR)/%.fuzz.o: %.c | $(OBJDIR)
357+
$(CC) $(CFLAGS_OPT) -fsanitize=fuzzer-no-link -c -o $@ $<
358+
338359
$(OBJDIR)/%.check.o: %.c | $(OBJDIR)
339360
$(CC) $(CFLAGS) -DCONFIG_CHECK_JSVALUE -c -o $@ $<
340361

@@ -346,7 +367,7 @@ unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c u
346367

347368
clean:
348369
rm -f repl.c qjscalc.c out.c
349-
rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS)
370+
rm -f *.a *.o *.d *~ unicode_gen regexp_test fuzz_eval fuzz_compile fuzz_regexp $(PROGS)
350371
rm -f hello.c test_fib.c
351372
rm -f examples/*.so tests/*.so
352373
rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug

fuzz/README

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
libFuzzer support for QuickJS
2+
=============================
3+
4+
Build QuickJS with libFuzzer support as follows:
5+
6+
CONFIG_CLANG=y make libfuzzer
7+
8+
This can be extended with sanitizer support to improve efficacy:
9+
10+
CONFIG_CLANG=y CONFIG_ASAN=y make libfuzzer
11+
12+
13+
Currently, there are three fuzzing targets defined: fuzz_eval, fuzz_compile and fuzz_regexp.
14+
The above build command will produce an executable binary for each of them, which can be
15+
simply executed as:
16+
17+
./fuzz_eval
18+
19+
or with an initial corpus:
20+
21+
./fuzz_compile corpus_dir/
22+
23+
or with a predefined dictionary to improve its efficacy:
24+
25+
./fuzz_eval -dict fuzz/fuzz.dict
26+
27+
or with arbitrary CLI arguments provided by libFuzzer (https://llvm.org/docs/LibFuzzer.html).

fuzz/fuzz.dict

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
"__loadScript"
2+
"abs"
3+
"acos"
4+
"acosh"
5+
"add"
6+
"AggregateError"
7+
"and"
8+
"apply"
9+
"Array"
10+
"ArrayBuffer"
11+
"asin"
12+
"asinh"
13+
"atan"
14+
"atan2"
15+
"atanh"
16+
"Atomics"
17+
"BigDecimal"
18+
"BigFloat"
19+
"BigFloatEnv"
20+
"BigInt"
21+
"BigInt64Array"
22+
"BigUint64Array"
23+
"Boolean"
24+
"cbrt"
25+
"ceil"
26+
"chdir"
27+
"clearTimeout"
28+
"close"
29+
"clz32"
30+
"compareExchange"
31+
"console"
32+
"construct"
33+
"cos"
34+
"cosh"
35+
"DataView"
36+
"Date"
37+
"decodeURI"
38+
"decodeURIComponent"
39+
"defineProperty"
40+
"deleteProperty"
41+
"dup"
42+
"dup2"
43+
"E"
44+
"encodeURI"
45+
"encodeURIComponent"
46+
"err"
47+
"Error"
48+
"escape"
49+
"eval"
50+
"EvalError"
51+
"evalScript"
52+
"exchange"
53+
"exec"
54+
"exit"
55+
"exp"
56+
"expm1"
57+
"fdopen"
58+
"Float32Array"
59+
"Float64Array"
60+
"floor"
61+
"fround"
62+
"Function"
63+
"gc"
64+
"get"
65+
"getcwd"
66+
"getenv"
67+
"getenviron"
68+
"getOwnPropertyDescriptor"
69+
"getpid"
70+
"getPrototypeOf"
71+
"globalThis"
72+
"has"
73+
"hypot"
74+
"imul"
75+
"in"
76+
"Infinity"
77+
"Int16Array"
78+
"Int32Array"
79+
"Int8Array"
80+
"InternalError"
81+
"isatty"
82+
"isExtensible"
83+
"isFinite"
84+
"isLockFree"
85+
"isNaN"
86+
"iterateBuiltIns"
87+
"JSON"
88+
"kill"
89+
"length"
90+
"LN10"
91+
"LN2"
92+
"load"
93+
"loadFile"
94+
"loadScript"
95+
"log"
96+
"log10"
97+
"LOG10E"
98+
"log1p"
99+
"log2"
100+
"LOG2E"
101+
"lstat"
102+
"Map"
103+
"Math"
104+
"max"
105+
"min"
106+
"mkdir"
107+
"NaN"
108+
"notify"
109+
"now"
110+
"Number"
111+
"O_APPEND"
112+
"O_CREAT"
113+
"O_EXCL"
114+
"O_RDONLY"
115+
"O_RDWR"
116+
"O_TRUNC"
117+
"O_WRONLY"
118+
"Object"
119+
"open"
120+
"Operators"
121+
"or"
122+
"os"
123+
"out"
124+
"ownKeys"
125+
"parse"
126+
"parseExtJSON"
127+
"parseFloat"
128+
"parseInt"
129+
"PI"
130+
"pipe"
131+
"platform"
132+
"popen"
133+
"pow"
134+
"preventExtensions"
135+
"print"
136+
"printf"
137+
"Promise"
138+
"Proxy"
139+
"puts"
140+
"random"
141+
"RangeError"
142+
"read"
143+
"readdir"
144+
"readlink"
145+
"realpath"
146+
"ReferenceError"
147+
"Reflect"
148+
"RegExp"
149+
"remove"
150+
"rename"
151+
"round"
152+
"S_IFBLK"
153+
"S_IFCHR"
154+
"S_IFDIR"
155+
"S_IFIFO"
156+
"S_IFLNK"
157+
"S_IFMT"
158+
"S_IFREG"
159+
"S_IFSOCK"
160+
"S_ISGID"
161+
"S_ISUID"
162+
"scriptArgs"
163+
"seek"
164+
"SEEK_CUR"
165+
"SEEK_END"
166+
"SEEK_SET"
167+
"set"
168+
"Set"
169+
"setenv"
170+
"setPrototypeOf"
171+
"setReadHandler"
172+
"setTimeout"
173+
"setWriteHandler"
174+
"SharedArrayBuffer"
175+
"SIGABRT"
176+
"SIGALRM"
177+
"SIGCHLD"
178+
"SIGCONT"
179+
"SIGFPE"
180+
"SIGILL"
181+
"SIGINT"
182+
"sign"
183+
"signal"
184+
"SIGPIPE"
185+
"SIGQUIT"
186+
"SIGSEGV"
187+
"SIGSTOP"
188+
"SIGTERM"
189+
"SIGTSTP"
190+
"SIGTTIN"
191+
"SIGTTOU"
192+
"SIGUSR1"
193+
"SIGUSR2"
194+
"sin"
195+
"sinh"
196+
"sleep"
197+
"sleepAsync"
198+
"sprintf"
199+
"sqrt"
200+
"SQRT1_2"
201+
"SQRT2"
202+
"stat"
203+
"std"
204+
"store"
205+
"strerror"
206+
"String"
207+
"stringify"
208+
"sub"
209+
"Symbol"
210+
"symlink"
211+
"SyntaxError"
212+
"tan"
213+
"tanh"
214+
"tmpfile"
215+
"trunc"
216+
"ttyGetWinSize"
217+
"ttySetRaw"
218+
"TypeError"
219+
"Uint16Array"
220+
"Uint32Array"
221+
"Uint8Array"
222+
"Uint8ClampedArray"
223+
"undefined"
224+
"unescape"
225+
"unsetenv"
226+
"URIError"
227+
"urlGet"
228+
"utimes"
229+
"wait"
230+
"waitpid"
231+
"WeakMap"
232+
"WeakSet"
233+
"WNOHANG"
234+
"Worker"
235+
"write"
236+
"xor"
237+
"v0"
238+
"v1"
239+
"v2"
240+
"v3"
241+
"v4"
242+
"v5"
243+
"v6"
244+
"v7"
245+
"v8"
246+
"v9"
247+
"v10"
248+
"v11"
249+
"v12"
250+
"v13"
251+
"v14"
252+
"v15"
253+
"v16"
254+
"v17"
255+
"v18"
256+
"v19"
257+
"v20"

fuzz/fuzz_common.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* Copyright 2020 Google Inc.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
#include "quickjs.h"
17+
#include "quickjs-libc.h"
18+
19+
static int nbinterrupts = 0;
20+
21+
void reset_nbinterrupts();
22+
void test_one_input_init(JSRuntime *rt, JSContext *ctx);

0 commit comments

Comments
 (0)