diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 4dedb040..180e9a36 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -17,4 +17,8 @@ jobs: steps: - uses: actions/checkout@v4 with: { fetch-depth: 2 } - - run: make -C test ${{ matrix.target }} + - run: make -C test ${{ matrix.target }} ARGS="-max_total_time=7200" + +# as we're not getting access to test units causing a problem, convert from the log: +# base64 -d > dataofdeath +# then paste the base64 data, enter, Ctrl-D; maybe check with hexdump -C dataofdeath diff --git a/mongoose.c b/mongoose.c index 9f185123..ba7bc6bd 100644 --- a/mongoose.c +++ b/mongoose.c @@ -11462,6 +11462,7 @@ static int mg_tls_server_recv_hello(struct mg_connection *c) { uint16_t key_exchange_len; uint8_t *key_exchange; uint16_t n = MG_LOAD_BE16(ext + j + 2); + if (((uint32_t) n + j + 4) > ext_len) goto fail; if (MG_LOAD_BE16(ext + j) != 0x0033) { // not a key share extension, ignore j += (uint16_t) (n + 4); continue; diff --git a/src/tls_builtin.c b/src/tls_builtin.c index 165cd66b..3dbccdae 100644 --- a/src/tls_builtin.c +++ b/src/tls_builtin.c @@ -597,6 +597,7 @@ static int mg_tls_server_recv_hello(struct mg_connection *c) { uint16_t key_exchange_len; uint8_t *key_exchange; uint16_t n = MG_LOAD_BE16(ext + j + 2); + if (((uint32_t) n + j + 4) > ext_len) goto fail; if (MG_LOAD_BE16(ext + j) != 0x0033) { // not a key share extension, ignore j += (uint16_t) (n + 4); continue; diff --git a/test/Makefile b/test/Makefile index d33dd61c..6b0bf815 100644 --- a/test/Makefile +++ b/test/Makefile @@ -117,7 +117,7 @@ unamalgamated: $(HDRS) Makefile packed_fs.c fuzz: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined fuzz: mongoose.c mongoose.h Makefile fuzz.c $(CC) fuzz.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer - $(RUN) ./fuzzer + $(RUN) ./fuzzer $(ARGS) FUZZDATA ?= /tmp/fuzzdata fuzz2: mongoose.c mongoose.h Makefile fuzz.c @@ -127,7 +127,11 @@ fuzz2: mongoose.c mongoose.h Makefile fuzz.c fuzz_tls: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined fuzz_tls: mongoose.c mongoose.h Makefile fuzz_tls.c $(CC) fuzz_tls.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer_tls - $(RUN) ./fuzzer_tls -max_len=17000 + $(RUN) ./fuzzer_tls -max_len=17000 $(ARGS) + +fuzz_tls2: mongoose.c mongoose.h Makefile fuzz_tls.c + $(CC) fuzz_tls.c -DMAIN $(OPTS) $(WARN) $(ASAN) $(INCS) -o fuzzer_tls + $(RUN) ./fuzzer_tls $(FUZZDATA) diff --git a/test/fuzz.c b/test/fuzz.c index c8a1e2aa..3b101be5 100644 --- a/test/fuzz.c +++ b/test/fuzz.c @@ -1,3 +1,5 @@ +// https://llvm.org/docs/LibFuzzer.html + #define MG_ENABLE_SOCKET 0 #define MG_ENABLE_LOG 0 #define MG_ENABLE_LINES 1 diff --git a/test/fuzz_tls.c b/test/fuzz_tls.c index 8249b6b5..309d4b80 100644 --- a/test/fuzz_tls.c +++ b/test/fuzz_tls.c @@ -1,3 +1,5 @@ +// https://llvm.org/docs/LibFuzzer.html + #define MG_ENABLE_SOCKET 1 #define MG_ENABLE_LOG 0 #define MG_ENABLE_LINES 1 @@ -12,28 +14,40 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t); #else int LLVMFuzzerTestOneInput(const uint8_t *, size_t); #endif -typedef int (*f)(struct mg_connection *); -f f_[] = { - mg_tls_server_recv_hello, -#if 0 - mg_tls_client_recv_hello, - mg_tls_client_recv_ext, - mg_tls_client_recv_cert, - mg_tls_client_recv_cert_verify -#endif +// Preprocessor magic, just add/remove functions here and leave the rest alone +#define TABLE(_) \ +_(mg_tls_server_recv_hello) \ +//_(mg_tls_client_recv_hello) \ +//_(mg_tls_client_recv_ext ) \ +//_(mg_tls_client_recv_cert) \ +//_(mg_tls_client_recv_cert_verify) \ +// ... + +struct f { + int (*f)(struct mg_connection *); + const char *name; }; +struct f f_[] = { +#define ENTRY(func) { func, #func }, +TABLE(ENTRY) +#undef ENTRY +}; +// end of preprocessor magic + + + int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - struct mg_connection c_[sizeof(f_)/sizeof(f)], *c = &c_[0]; - struct tls_data tls_[sizeof(f_)/sizeof(f)]; + struct mg_connection c_[sizeof(f_)/sizeof(struct f)], *c = &c_[0]; + struct tls_data tls_[sizeof(f_)/sizeof(struct f)]; int i; if (size == 0) return 0; mg_log_set(MG_LL_INFO); memset(c, 0, sizeof(*c)); c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE; c->is_tls = c->is_tls_hs = 1; - for (i = 0; i < (int)(sizeof(f_)/sizeof(f)); i++) { + for (i = 0; i < (int)(sizeof(f_)/sizeof(struct f)); i++) { struct mg_iobuf *io; c = &c_[i]; io = &c->rtls; @@ -47,7 +61,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { memcpy(&io->buf[io->len], data, size); io->len += size; c->tls = &tls_[i]; - f_[i](&c[i]); +#ifdef PRINT_FUNCNAME + printf("CALLING %s\n", f_[i].name); +#endif + f_[i].f(&c[i]); mg_iobuf_free(io); }