From c16cf5a2a77a98382110702ba24c35d63584efe9 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Tue, 19 Nov 2019 23:57:28 +0300 Subject: [PATCH] [njs] Moving fuzzing target upstream. (#3047) --- projects/njs/Dockerfile | 4 +- projects/njs/build.sh | 14 +- projects/njs/njs_process_script_fuzzer.c | 664 ----------------------- 3 files changed, 5 insertions(+), 677 deletions(-) delete mode 100644 projects/njs/njs_process_script_fuzzer.c diff --git a/projects/njs/Dockerfile b/projects/njs/Dockerfile index 41f2940a4..05bf5dd77 100644 --- a/projects/njs/Dockerfile +++ b/projects/njs/Dockerfile @@ -17,9 +17,9 @@ FROM gcr.io/oss-fuzz-base/base-builder MAINTAINER mmoroz@chromium.org RUN apt-get update && apt-get install -y make autoconf automake libtool \ - mercurial libpcre3-dev libreadline-dev subversion + mercurial libpcre3-dev subversion RUN hg clone http://hg.nginx.org/njs RUN svn co svn://vcs.exim.org/pcre/code/trunk pcre WORKDIR njs -COPY build.sh njs_process_script_fuzzer.c $SRC/ +COPY build.sh $SRC/ diff --git a/projects/njs/build.sh b/projects/njs/build.sh index 7b1afa082..94abb6266 100755 --- a/projects/njs/build.sh +++ b/projects/njs/build.sh @@ -26,18 +26,10 @@ popd # build project rm -rf build -./configure -make njs +./configure --debug=YES +make njs_fuzzer -# build fuzzers -# e.g. -$CC $CFLAGS -Inxt -Ibuild -Isrc -c \ - $SRC/njs_process_script_fuzzer.c -o build/njs_process_script_fuzzer.o - -$CXX $CXXFLAGS build/njs_process_script_fuzzer.o \ - -o $OUT/njs_process_script_fuzzer \ - $LIB_FUZZING_ENGINE build/libnjs.a \ - $SRC/pcre/.libs/libpcre.a -lm -lreadline +cp ./build/njs_process_script_fuzzer $OUT/ SEED_CORPUS_PATH=$OUT/njs_process_script_fuzzer_seed_corpus mkdir -p $SEED_CORPUS_PATH diff --git a/projects/njs/njs_process_script_fuzzer.c b/projects/njs/njs_process_script_fuzzer.c deleted file mode 100644 index 09938b99c..000000000 --- a/projects/njs/njs_process_script_fuzzer.c +++ /dev/null @@ -1,664 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include -#include - -// The vast majority of the code was copied from njs/njs_shell.c. - -typedef struct { - uint8_t disassemble; - uint8_t interactive; - uint8_t module; - uint8_t quiet; - uint8_t sandbox; - uint8_t version; - - char *file; - char *command; - size_t n_paths; - char **paths; -} njs_opts_t; - - -typedef struct { - size_t index; - size_t length; - njs_array_t *completions; - njs_array_t *suffix_completions; - njs_lvlhsh_each_t lhe; - - enum { - NJS_COMPLETION_VAR = 0, - NJS_COMPLETION_SUFFIX, - NJS_COMPLETION_GLOBAL - } phase; -} njs_completion_t; - - -typedef struct { - njs_vm_event_t vm_event; - njs_queue_link_t link; -} njs_ev_t; - - -typedef struct { - njs_vm_t *vm; - - njs_lvlhsh_t events; /* njs_ev_t * */ - njs_queue_t posted_events; - - uint64_t time; - - njs_completion_t completion; -} njs_console_t; - - -static njs_int_t njs_console_init(njs_vm_t *vm, njs_console_t *console); -static njs_int_t njs_externals_init(njs_vm_t *vm, njs_console_t *console); -static njs_int_t njs_interactive_shell(njs_opts_t *opts, - njs_vm_opt_t *vm_options, njs_str_t *line); -static njs_vm_t *njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options); -static njs_int_t njs_process_script(njs_console_t *console, njs_opts_t *opts, - const njs_str_t *script); - -static njs_int_t njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_ext_console_dump(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); -static njs_int_t njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, - njs_uint_t nargs, njs_index_t unused); - -static njs_host_event_t njs_console_set_timer(njs_external_ptr_t external, - uint64_t delay, njs_vm_event_t vm_event); -static void njs_console_clear_timer(njs_external_ptr_t external, - njs_host_event_t event); - -static njs_int_t lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data); -static void *lvlhsh_pool_alloc(void *pool, size_t size, njs_uint_t nalloc); -static void lvlhsh_pool_free(void *pool, void *p, size_t size); - - -static njs_external_t njs_ext_console[] = { - - { njs_str("log"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - njs_ext_console_log, - 0 }, - - { njs_str("dump"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - njs_ext_console_dump, - 0 }, - - { njs_str("time"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - njs_ext_console_time, - 0 }, - - { njs_str("timeEnd"), - NJS_EXTERN_METHOD, - NULL, - 0, - NULL, - NULL, - NULL, - NULL, - NULL, - njs_ext_console_time_end, - 0 }, -}; - -static njs_external_t njs_externals[] = { - - { njs_str("console"), - NJS_EXTERN_OBJECT, - njs_ext_console, - njs_nitems(njs_ext_console), - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0 }, -}; - - -static const njs_lvlhsh_proto_t lvlhsh_proto njs_aligned(64) = { - NJS_LVLHSH_LARGE_SLAB, - 0, - lvlhsh_key_test, - lvlhsh_pool_alloc, - lvlhsh_pool_free, -}; - - -static njs_vm_ops_t njs_console_ops = { - njs_console_set_timer, - njs_console_clear_timer -}; - - -static njs_console_t njs_console; - - -static njs_int_t -njs_console_init(njs_vm_t *vm, njs_console_t *console) -{ - console->vm = vm; - - njs_lvlhsh_init(&console->events); - njs_queue_init(&console->posted_events); - - console->time = UINT64_MAX; - - console->completion.completions = njs_vm_completions(vm, NULL); - if (console->completion.completions == NULL) { - return NJS_ERROR; - } - - return NJS_OK; -} - - -static njs_int_t -njs_externals_init(njs_vm_t *vm, njs_console_t *console) -{ - njs_uint_t ret; - njs_value_t *value; - const njs_extern_t *proto; - - static const njs_str_t name = njs_str("console"); - - proto = njs_vm_external_prototype(vm, &njs_externals[0]); - if (proto == NULL) { - njs_stderror("failed to add console proto\n"); - return NJS_ERROR; - } - - value = njs_mp_zalloc(vm->mem_pool, sizeof(njs_opaque_value_t)); - if (value == NULL) { - return NJS_ERROR; - } - - ret = njs_vm_external_create(vm, value, proto, console); - if (ret != NJS_OK) { - return NJS_ERROR; - } - - ret = njs_vm_external_bind(vm, &name, value); - if (ret != NJS_OK) { - return NJS_ERROR; - } - - ret = njs_console_init(vm, console); - if (ret != NJS_OK) { - return NJS_ERROR; - } - - return NJS_OK; -} - -static njs_int_t -njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options, njs_str_t *line) -{ - njs_vm_t *vm; - - vm = njs_create_vm(opts, vm_options); - if (vm == NULL) { - return NJS_ERROR; - } - - njs_process_script(vm_options->external, opts, line); - njs_vm_destroy(vm); - vm = NULL; - - return NJS_OK; -} - -static njs_vm_t * -njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options) -{ - u_char *p, *start; - njs_vm_t *vm; - njs_int_t ret; - njs_str_t path; - njs_uint_t i; - - vm = njs_vm_create(vm_options); - if (vm == NULL) { - njs_stderror("failed to create vm\n"); - return NULL; - } - - if (njs_externals_init(vm, vm_options->external) != NJS_OK) { - njs_stderror("failed to add external protos\n"); - return NULL; - } - - for (i = 0; i < opts->n_paths; i++) { - path.start = (u_char *) opts->paths[i]; - path.length = njs_strlen(opts->paths[i]); - - ret = njs_vm_add_path(vm, &path); - if (ret != NJS_OK) { - njs_stderror("failed to add path\n"); - return NULL; - } - } - - start = (u_char *) getenv("NJS_PATH"); - if (start == NULL) { - return vm; - } - - for ( ;; ) { - p = njs_strchr(start, ':'); - - path.start = start; - path.length = (p != NULL) ? (size_t) (p - start) : njs_strlen(start); - - ret = njs_vm_add_path(vm, &path); - if (ret != NJS_OK) { - njs_stderror("failed to add path\n"); - return NULL; - } - - if (p == NULL) { - break; - } - - start = p + 1; - } - - return vm; -} - - -static njs_int_t -njs_process_events(njs_console_t *console, njs_opts_t *opts) -{ - njs_ev_t *ev; - njs_queue_t *events; - njs_queue_link_t *link; - - events = &console->posted_events; - - for ( ;; ) { - link = njs_queue_first(events); - - if (link == njs_queue_tail(events)) { - break; - } - - ev = njs_queue_link_data(link, njs_ev_t, link); - - njs_queue_remove(&ev->link); - ev->link.prev = NULL; - ev->link.next = NULL; - - njs_vm_post_event(console->vm, ev->vm_event, NULL, 0); - } - - return NJS_OK; -} - - -static njs_int_t -njs_process_script(njs_console_t *console, njs_opts_t *opts, - const njs_str_t *script) -{ - u_char *start; - njs_vm_t *vm; - njs_int_t ret; - - vm = console->vm; - start = script->start; - - ret = njs_vm_compile(vm, &start, start + script->length); - - if (ret == NJS_OK) { - if (opts->disassemble) { - njs_disassembler(vm); - njs_printf("\n"); - } - - ret = njs_vm_start(vm); - } - - for ( ;; ) { - if (!njs_vm_pending(vm)) { - break; - } - - ret = njs_process_events(console, opts); - if (njs_slow_path(ret != NJS_OK)) { - njs_stderror("njs_process_events() failed\n"); - ret = NJS_ERROR; - break; - } - - if (njs_vm_waiting(vm) && !njs_vm_posted(vm)) { - /*TODO: async events. */ - - njs_stderror("njs_process_script(): async events unsupported\n"); - ret = NJS_ERROR; - break; - } - - ret = njs_vm_run(vm); - } - - return ret; -} - - -static njs_int_t -njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_str_t msg; - njs_uint_t n; - - n = 1; - - while (n < nargs) { - if (njs_vm_value_dump(vm, &msg, njs_argument(args, n), 1, 0) - == NJS_ERROR) - { - return NJS_ERROR; - } - - njs_printf("%s", (n != 1) ? " " : ""); - njs_print(msg.start, msg.length); - - n++; - } - - if (nargs > 1) { - njs_printf("\n"); - } - - vm->retval = njs_value_undefined; - - return NJS_OK; -} - - -static njs_int_t -njs_ext_console_dump(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_str_t msg; - njs_uint_t n; - - n = 1; - - while (n < nargs) { - if (njs_vm_value_dump(vm, &msg, njs_argument(args, n), 1, 1) - == NJS_ERROR) - { - return NJS_ERROR; - } - - njs_printf("%s", (n != 1) ? " " : ""); - njs_print(msg.start, msg.length); - - n++; - } - - if (nargs > 1) { - njs_printf("\n"); - } - - vm->retval = njs_value_undefined; - - return NJS_OK; -} - - -static njs_int_t -njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - njs_console_t *console; - - if (!njs_value_is_undefined(njs_arg(args, nargs, 1))) { - njs_vm_error(vm, "labels not implemented"); - return NJS_ERROR; - } - - console = njs_vm_external(vm, njs_arg(args, nargs, 0)); - if (njs_slow_path(console == NULL)) { - return NJS_ERROR; - } - - console->time = njs_time(); - - vm->retval = njs_value_undefined; - - return NJS_OK; -} - - -static njs_int_t -njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, - njs_index_t unused) -{ - uint64_t ns, ms; - njs_console_t *console; - - ns = njs_time(); - - if (!njs_value_is_undefined(njs_arg(args, nargs, 1))) { - njs_vm_error(vm, "labels not implemented"); - return NJS_ERROR; - } - - console = njs_vm_external(vm, njs_arg(args, nargs, 0)); - if (njs_slow_path(console == NULL)) { - return NJS_ERROR; - } - - if (njs_fast_path(console->time != UINT64_MAX)) { - - ns = ns - console->time; - - ms = ns / 1000000; - ns = ns % 1000000; - - njs_printf("default: %uL.%06uLms\n", ms, ns); - - console->time = UINT64_MAX; - - } else { - njs_printf("Timer \"default\" doesn’t exist.\n"); - } - - vm->retval = njs_value_undefined; - - return NJS_OK; -} - - -static njs_host_event_t -njs_console_set_timer(njs_external_ptr_t external, uint64_t delay, - njs_vm_event_t vm_event) -{ - njs_ev_t *ev; - njs_vm_t *vm; - njs_int_t ret; - njs_console_t *console; - njs_lvlhsh_query_t lhq; - - if (delay != 0) { - njs_stderror("njs_console_set_timer(): async timers unsupported\n"); - return NULL; - } - - console = external; - vm = console->vm; - - ev = njs_mp_alloc(vm->mem_pool, sizeof(njs_ev_t)); - if (njs_slow_path(ev == NULL)) { - return NULL; - } - - ev->vm_event = vm_event; - - lhq.key.start = (u_char *) &ev->vm_event; - lhq.key.length = sizeof(njs_vm_event_t); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); - - lhq.replace = 0; - lhq.value = ev; - lhq.proto = &lvlhsh_proto; - lhq.pool = vm->mem_pool; - - ret = njs_lvlhsh_insert(&console->events, &lhq); - if (njs_slow_path(ret != NJS_OK)) { - return NULL; - } - - njs_queue_insert_tail(&console->posted_events, &ev->link); - - return (njs_host_event_t) ev; -} - - -static void -njs_console_clear_timer(njs_external_ptr_t external, njs_host_event_t event) -{ - njs_vm_t *vm; - njs_ev_t *ev; - njs_int_t ret; - njs_console_t *console; - njs_lvlhsh_query_t lhq; - - ev = event; - console = external; - vm = console->vm; - - lhq.key.start = (u_char *) &ev->vm_event; - lhq.key.length = sizeof(njs_vm_event_t); - lhq.key_hash = njs_djb_hash(lhq.key.start, lhq.key.length); - - lhq.proto = &lvlhsh_proto; - lhq.pool = vm->mem_pool; - - if (ev->link.prev != NULL) { - njs_queue_remove(&ev->link); - } - - ret = njs_lvlhsh_delete(&console->events, &lhq); - if (ret != NJS_OK) { - njs_stderror("njs_lvlhsh_delete() failed\n"); - } - - njs_mp_free(vm->mem_pool, ev); -} - - -static njs_int_t -lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data) -{ - njs_ev_t *ev; - - ev = data; - - if (memcmp(&ev->vm_event, lhq->key.start, sizeof(njs_vm_event_t)) == 0) { - return NJS_OK; - } - - return NJS_DECLINED; -} - - -static void * -lvlhsh_pool_alloc(void *pool, size_t size, njs_uint_t nalloc) -{ - return njs_mp_align(pool, size, size); -} - - -static void -lvlhsh_pool_free(void *pool, void *p, size_t size) -{ - njs_mp_free(pool, p); -} - - -int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - if (size == 0) return 0; - - char* input = malloc(size); - memcpy(input, data, size); - njs_str_t line = {size, input}; - - njs_vm_t *vm; - njs_int_t ret; - njs_opts_t opts; - njs_str_t command; - njs_vm_opt_t vm_options; - - njs_memzero(&opts, sizeof(njs_opts_t)); - opts.interactive = 1; - - njs_memzero(&vm_options, sizeof(njs_vm_opt_t)); - - vm_options.init = !opts.interactive; - vm_options.accumulative = opts.interactive; - vm_options.backtrace = 1; - vm_options.quiet = opts.quiet; - vm_options.sandbox = opts.sandbox; - vm_options.module = opts.module; - - vm_options.ops = &njs_console_ops; - vm_options.external = &njs_console; - - ret = njs_interactive_shell(&opts, &vm_options, &line); - free(input); - - if (ret != NJS_OK) - return 0; - - return 0; -}