[njs] Introduced njs_fuzzer target.
Dmitry Volyntsev
xeioex at nginx.com
Tue Nov 19 20:05:00 UTC 2019
details: https://hg.nginx.org/njs/rev/884d3a86beab
branches:
changeset: 1246:884d3a86beab
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Tue Nov 19 19:32:26 2019 +0300
description:
Introduced njs_fuzzer target.
diffstat:
auto/make | 27 ++++
src/njs_shell.c | 324 +++++++++++++++++++++++++++++++++----------------------
2 files changed, 218 insertions(+), 133 deletions(-)
diffs (494 lines):
diff -r 452ce96df2e3 -r 884d3a86beab auto/make
--- a/auto/make Tue Nov 19 19:19:53 2019 +0300
+++ b/auto/make Tue Nov 19 19:32:26 2019 +0300
@@ -121,6 +121,31 @@ END
fi
+
+# njs fuzzer.
+
+cat << END >> $NJS_MAKEFILE
+
+$NJS_BUILD_DIR/njs_process_script_fuzzer.o: \\
+ src/njs_shell.c
+ \$(NJS_CC) -c \$(CFLAGS) $NJS_LIB_AUX_CFLAGS \\
+ \$(NJS_LIB_INCS) -Injs \\
+ -DNJS_FUZZER_TARGET \\
+ -o $NJS_BUILD_DIR/njs_process_script_fuzzer.o \\
+ src/njs_shell.c
+
+$NJS_BUILD_DIR/njs_process_script_fuzzer: \\
+ $NJS_BUILD_DIR/libnjs.a \\
+ $NJS_BUILD_DIR/njs_process_script_fuzzer.o
+ \$(CXX) \$(CXXFLAGS) -o $NJS_BUILD_DIR/njs_process_script_fuzzer \\
+ $NJS_LIB_AUX_CFLAGS \$(NJS_LIB_INCS) -Injs \\
+ \$(LIB_FUZZING_ENGINE) \\
+ $NJS_BUILD_DIR/njs_process_script_fuzzer.o \\
+ $NJS_BUILD_DIR/libnjs.a \\
+ -lm $NJS_LIBS $NJS_LIB_AUX_LIBS
+
+END
+
# lib tests.
for njs_src in $NJS_LIB_TEST_SRCS
@@ -186,6 +211,8 @@ all: $NJS_BUILD_DIR/njs_auto_config.h \\
$NJS_DEFAULT_TARGET test lib_test benchmark
njs: $NJS_BUILD_DIR/njs_auto_config.h $NJS_BUILD_DIR/njs
+njs_fuzzer: $NJS_BUILD_DIR/njs_auto_config.h \\
+ $NJS_BUILD_DIR/njs_process_script_fuzzer
lib_test: $NJS_BUILD_DIR/njs_auto_config.h \\
$NJS_BUILD_DIR/random_unit_test \\
diff -r 452ce96df2e3 -r 884d3a86beab src/njs_shell.c
--- a/src/njs_shell.c Tue Nov 19 19:19:53 2019 +0300
+++ b/src/njs_shell.c Tue Nov 19 19:32:26 2019 +0300
@@ -6,6 +6,9 @@
#include <njs_main.h>
+
+#ifndef NJS_FUZZER_TARGET
+
#include <locale.h>
#if (NJS_HAVE_EDITLINE)
#include <editline/readline.h>
@@ -18,12 +21,15 @@
#endif
#endif
+#endif
+
typedef struct {
uint8_t disassemble;
uint8_t interactive;
uint8_t module;
uint8_t quiet;
+ uint8_t silent;
uint8_t sandbox;
uint8_t safe;
uint8_t version;
@@ -74,19 +80,23 @@ typedef struct {
} njs_console_t;
-static njs_int_t njs_get_options(njs_opts_t *opts, int argc, char **argv);
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_vm_t *njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options);
+static njs_int_t njs_process_script(njs_opts_t *opts,
+ njs_console_t *console, const njs_str_t *script);
+
+#ifndef NJS_FUZZER_TARGET
+
+static njs_int_t njs_get_options(njs_opts_t *opts, int argc, char **argv);
+static njs_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options);
static njs_int_t njs_interactive_shell(njs_opts_t *opts,
njs_vm_opt_t *vm_options);
-static njs_vm_t *njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options);
-static njs_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options);
-static njs_int_t njs_process_script(njs_console_t *console,
- const njs_str_t *script);
static njs_int_t njs_editline_init(void);
-static char **njs_completion_handler(const char *text, int start, int end);
static char *njs_completion_generator(const char *text, int state);
+#endif
+
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,
@@ -195,6 +205,8 @@ static njs_vm_ops_t njs_console_ops = {
static njs_console_t njs_console;
+#ifndef NJS_FUZZER_TARGET
+
int
main(int argc, char **argv)
{
@@ -265,7 +277,7 @@ main(int argc, char **argv)
if (vm != NULL) {
command.start = (u_char *) opts.command;
command.length = njs_strlen(opts.command);
- ret = njs_process_script(vm_options.external, &command);
+ ret = njs_process_script(&opts, vm_options.external, &command);
}
} else {
@@ -400,109 +412,6 @@ njs_get_options(njs_opts_t *opts, int ar
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);
-
- njs_lvlhsh_init(&console->labels);
-
- 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_vm_t *vm;
- njs_str_t line;
-
- if (njs_editline_init() != NJS_OK) {
- njs_stderror("failed to init completions\n");
- return NJS_ERROR;
- }
-
- vm = njs_create_vm(opts, vm_options);
- if (vm == NULL) {
- return NJS_ERROR;
- }
-
- if (!opts->quiet) {
- njs_printf("interactive njs %s\n\n", NJS_VERSION);
-
- njs_printf("v.<Tab> -> the properties and prototype methods of v.\n\n");
- }
-
- for ( ;; ) {
- line.start = (u_char *) readline(">> ");
- if (line.start == NULL) {
- break;
- }
-
- line.length = njs_strlen(line.start);
- if (line.length == 0) {
- continue;
- }
-
- add_history((char *) line.start);
-
- njs_process_script(vm_options->external, &line);
-
- /* editline allocs a new buffer every time. */
- free(line.start);
- }
-
- return NJS_OK;
-}
-
-
-static njs_int_t
njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options)
{
int fd;
@@ -612,7 +521,7 @@ njs_process_file(njs_opts_t *opts, njs_v
}
}
- ret = njs_process_script(vm_options->external, &script);
+ ret = njs_process_script(opts, vm_options->external, &script);
if (ret != NJS_OK) {
ret = NJS_ERROR;
goto done;
@@ -635,6 +544,103 @@ close_fd:
return ret;
}
+#else
+
+int
+LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ njs_vm_t *vm;
+ njs_opts_t opts;
+ njs_str_t script;
+ njs_vm_opt_t vm_options;
+
+ if (size == 0) {
+ return 0;
+ }
+
+ njs_memzero(&opts, sizeof(njs_opts_t));
+
+ opts.silent = 1;
+
+ njs_memzero(&vm_options, sizeof(njs_vm_opt_t));
+
+ vm_options.init = 1;
+ vm_options.backtrace = 0;
+ vm_options.ops = &njs_console_ops;
+ vm_options.external = &njs_console;
+
+ vm = njs_create_vm(&opts, &vm_options);
+
+ if (njs_fast_path(vm != NULL)) {
+ script.length = size;
+ script.start = (u_char *) data;
+
+ (void) njs_process_script(&opts, vm_options.external, &script);
+ njs_vm_destroy(vm);
+ }
+
+ return 0;
+}
+
+#endif
+
+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);
+
+ njs_lvlhsh_init(&console->labels);
+
+ 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_vm_t *
njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options)
@@ -696,21 +702,23 @@ njs_create_vm(njs_opts_t *opts, njs_vm_o
static void
-njs_output(njs_vm_t *vm, njs_int_t ret)
+njs_output(njs_opts_t *opts, njs_vm_t *vm, njs_int_t ret)
{
njs_str_t out;
- if (njs_vm_retval_dump(vm, &out, 1) != NJS_OK) {
- out = njs_str_value("failed to get retval from VM");
- ret = NJS_ERROR;
- }
+ if (!opts->silent) {
+ if (njs_vm_retval_dump(vm, &out, 1) != NJS_OK) {
+ out = njs_str_value("failed to get retval from VM");
+ ret = NJS_ERROR;
+ }
- if (ret != NJS_OK) {
- njs_stderror("%V\n", &out);
+ if (ret != NJS_OK) {
+ njs_stderror("%V\n", &out);
- } else if (vm->options.accumulative) {
- njs_print(out.start, out.length);
- njs_printf("\n");
+ } else if (vm->options.accumulative) {
+ njs_print(out.start, out.length);
+ njs_printf("\n");
+ }
}
}
@@ -745,7 +753,8 @@ njs_process_events(njs_console_t *consol
static njs_int_t
-njs_process_script(njs_console_t *console, const njs_str_t *script)
+njs_process_script(njs_opts_t *opts, njs_console_t *console,
+ const njs_str_t *script)
{
u_char *start;
njs_vm_t *vm;
@@ -760,7 +769,7 @@ njs_process_script(njs_console_t *consol
ret = njs_vm_start(vm);
}
- njs_output(vm, ret);
+ njs_output(opts, vm, ret);
for ( ;; ) {
if (!njs_vm_pending(vm)) {
@@ -785,7 +794,7 @@ njs_process_script(njs_console_t *consol
ret = njs_vm_run(vm);
if (ret == NJS_ERROR) {
- njs_output(vm, ret);
+ njs_output(opts, vm, ret);
}
}
@@ -793,6 +802,62 @@ njs_process_script(njs_console_t *consol
}
+#ifndef NJS_FUZZER_TARGET
+
+static njs_int_t
+njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options)
+{
+ njs_vm_t *vm;
+ njs_str_t line;
+
+ if (njs_editline_init() != NJS_OK) {
+ njs_stderror("failed to init completions\n");
+ return NJS_ERROR;
+ }
+
+ vm = njs_create_vm(opts, vm_options);
+ if (vm == NULL) {
+ return NJS_ERROR;
+ }
+
+ if (!opts->quiet) {
+ njs_printf("interactive njs %s\n\n", NJS_VERSION);
+
+ njs_printf("v.<Tab> -> the properties and prototype methods of v.\n\n");
+ }
+
+ for ( ;; ) {
+ line.start = (u_char *) readline(">> ");
+ if (line.start == NULL) {
+ break;
+ }
+
+ line.length = njs_strlen(line.start);
+ if (line.length == 0) {
+ continue;
+ }
+
+ add_history((char *) line.start);
+
+ njs_process_script(opts, vm_options->external, &line);
+
+ /* editline allocs a new buffer every time. */
+ free(line.start);
+ }
+
+ return NJS_OK;
+}
+
+
+static char **
+njs_completion_handler(const char *text, int start, int end)
+{
+ rl_attempted_completion_over = 1;
+
+ return rl_completion_matches(text, njs_completion_generator);
+}
+
+
static njs_int_t
njs_editline_init(void)
{
@@ -806,15 +871,6 @@ njs_editline_init(void)
}
-static char **
-njs_completion_handler(const char *text, int start, int end)
-{
- rl_attempted_completion_over = 1;
-
- return rl_completion_matches(text, njs_completion_generator);
-}
-
-
/* editline frees the buffer every time. */
#define njs_editline(s) strndup((char *) (s)->start, (s)->length)
@@ -961,6 +1017,8 @@ next:
return NULL;
}
+#endif
+
static njs_int_t
njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
More information about the nginx-devel
mailing list