From cfe2afa545f026bf2d1aabf77212cd68e31b938d Mon Sep 17 00:00:00 2001 From: bel2125 Date: Mon, 15 Feb 2021 14:21:07 +0100 Subject: [PATCH] Fuzz test: Fix all build warnings --- fuzztest/build.sh | 6 +- fuzztest/build_and_run.sh | 6 +- fuzztest/build_with_all.sh | 24 +++ fuzztest/fuzzmain.c | 372 +++++++++++++++++++++---------------- 4 files changed, 242 insertions(+), 166 deletions(-) create mode 100644 fuzztest/build_with_all.sh diff --git a/fuzztest/build.sh b/fuzztest/build.sh index 725810ca..cb2a82ff 100644 --- a/fuzztest/build.sh +++ b/fuzztest/build.sh @@ -3,11 +3,11 @@ make clean rm civetweb_fuzz? -make WITH_ALL=1 TEST_FUZZ=1 +make TEST_FUZZ=1 mv civetweb civetweb_fuzz1 -make WITH_ALL=1 TEST_FUZZ=2 +make TEST_FUZZ=2 mv civetweb civetweb_fuzz2 -make WITH_ALL=1 TEST_FUZZ=3 +make TEST_FUZZ=3 mv civetweb civetweb_fuzz3 echo "" diff --git a/fuzztest/build_and_run.sh b/fuzztest/build_and_run.sh index 40fa7f85..3d2d5574 100644 --- a/fuzztest/build_and_run.sh +++ b/fuzztest/build_and_run.sh @@ -11,7 +11,7 @@ echo "== run fuzz test 1 ==" echo "=====================" echo "" -./civetweb_fuzz1 -max_total_time=600 -max_len=2048 fuzztest/url/ +./civetweb_fuzz1 -max_total_time=60 -max_len=2048 fuzztest/url/ echo "" echo "=====================" @@ -19,7 +19,7 @@ echo "== run fuzz test 2 ==" echo "=====================" echo "" -./civetweb_fuzz2 -max_total_time=600 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1/ +./civetweb_fuzz2 -max_total_time=60 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1/ echo "" echo "=====================" @@ -27,7 +27,7 @@ echo "== run fuzz test 3 ==" echo "=====================" echo "" -./civetweb_fuzz3 -max_total_time=600 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1c/ +./civetweb_fuzz3 -max_total_time=60 -max_len=2048 -dict=fuzztest/http1.dict fuzztest/http1c/ echo "" echo "=====================" diff --git a/fuzztest/build_with_all.sh b/fuzztest/build_with_all.sh new file mode 100644 index 00000000..725810ca --- /dev/null +++ b/fuzztest/build_with_all.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +make clean +rm civetweb_fuzz? + +make WITH_ALL=1 TEST_FUZZ=1 +mv civetweb civetweb_fuzz1 +make WITH_ALL=1 TEST_FUZZ=2 +mv civetweb civetweb_fuzz2 +make WITH_ALL=1 TEST_FUZZ=3 +mv civetweb civetweb_fuzz3 + +echo "" +echo "=====================" +echo "== Build completed ==" +echo "=====================" +echo "" + +ls -halt civetweb* +md5sum civetweb_fuzz* + +echo "" +echo "=====================" +echo "" diff --git a/fuzztest/fuzzmain.c b/fuzztest/fuzzmain.c index 9bc1b4e9..2e09a915 100644 --- a/fuzztest/fuzzmain.c +++ b/fuzztest/fuzzmain.c @@ -19,7 +19,7 @@ typedef int SOCKET; #define closesocket(a) (close(a)) -#endif +#endif // not _WIN32 /* Port configuration */ @@ -28,6 +28,7 @@ unsigned short PORT_NUM_HTTP = 0; /* set dynamically */ #define TESTabort() \ { \ + fprintf(stderr, "!!! Precondition in test environment not met !!!\n"); \ fprintf(stderr, "!!! aborting fuzz test in line %u !!!", __LINE__); \ abort(); \ } @@ -35,7 +36,13 @@ unsigned short PORT_NUM_HTTP = 0; /* set dynamically */ static uint64_t call_count = 0; -static struct mg_context *ctx; + +/********************************************************/ +/* Init CivetWeb server ... test with mock client */ +/********************************************************/ +#if defined(TEST_FUZZ1) || defined(TEST_FUZZ2) + +static struct mg_context *ctx = 0; static const char *OPTIONS[] = {"listening_ports", "0", /* port: auto */ "document_root", @@ -43,16 +50,24 @@ static const char *OPTIONS[] = {"listening_ports", NULL, NULL}; +static void +civetweb_exit(void) +{ + printf("CivetWeb server exit\n"); + mg_stop(ctx); + ctx = 0; + test_sleep(5); +} + static void -init_civetweb(void) +civetweb_init(void) { struct mg_callbacks callbacks; struct mg_server_port ports[8]; memset(&callbacks, 0, sizeof(callbacks)); memset(&ports, 0, sizeof(ports)); - ctx = mg_start(&callbacks, 0, OPTIONS); if (!ctx) { @@ -81,160 +96,16 @@ init_civetweb(void) * when testing starting/stopping the server multiple times in test * container environments. */ test_sleep(5); + atexit(civetweb_exit); } -struct tcp_func_prm { - SOCKET sock; -}; - - -struct tRESPONSE { - char data[4096]; - size_t size; -} RESPONSE; - - -static void * -tcp_func(void *arg) -{ - char req[1024 * 16]; - SOCKET svr = (SOCKET)(-1); - - /* Get thread parameters and free arg */ - { - struct tcp_func_prm *ptcp_func_prm = (struct tcp_func_prm *)arg; - svr = ptcp_func_prm->sock; - free(arg); - } - - printf("MOCK server ready, sock %i\n", svr); - -next_request : { - struct sockaddr_in cliadr; - socklen_t adrlen = sizeof(cliadr); - int buf_filled = 0; - int req_ready = 0; - - memset(&cliadr, 0, sizeof(cliadr)); - - SOCKET cli = accept(svr, (struct sockaddr *)&cliadr, &adrlen); - - if (cli == -1) { - int er = errno; - fprintf(stderr, "Error: Accept failed [%s]\n", strerror(er)); - test_sleep(1); - goto next_request; - } - - /* Read request */ - do { - int r = recv(cli, req + buf_filled, sizeof(req) - buf_filled - 1, 0); - if (r > 0) { - buf_filled += r; - req[buf_filled] = 0; - if (strstr(req, "\r\n\r\n") != NULL) { - req_ready = 1; - } - } else { - /* some error */ - int er = errno; - fprintf(stderr, "Error: Recv failed [%s]\n", strerror(er)); - test_sleep(1); - goto next_request; - } - } while (!req_ready); - - /* Request is complete here. - * Now send response */ - send(cli, RESPONSE.data, RESPONSE.size, MSG_NOSIGNAL); - - /* Close connection. */ - shutdown(cli, SHUT_RDWR); - closesocket(cli); - - /* done */ - goto next_request; -} -} - - -static void -init_tcp(void) -{ - int r; - int bind_success = 0; - SOCKET sock = socket(AF_INET, SOCK_STREAM, 6); - if (sock == -1) { - r = errno; - fprintf(stderr, "Error: Cannot create socket [%s]\n", strerror(r)); - TESTabort(); - } - - for (PORT_NUM_HTTP = 1024; PORT_NUM_HTTP != 0; PORT_NUM_HTTP++) { - struct sockaddr_in sin; - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = inet_addr("127.0.0.1"); - sin.sin_port = htons(PORT_NUM_HTTP); - r = bind(sock, (struct sockaddr *)&sin, sizeof(sin)); - if (r == 0) { - bind_success = 1; - break; - } - r = errno; - fprintf(stderr, "Warning: Cannot bind [%s]\n", strerror(r)); - } - - if (!bind_success) { - fprintf(stderr, "Error: Cannot bind to any port\n"); - closesocket(sock); - TESTabort(); - } - - printf("MOCK server running on port %i\n", (int)PORT_NUM_HTTP); - - r = listen(sock, 128); - if (r != 0) { - r = errno; - fprintf(stderr, "Error: Cannot listen [%s]\n", strerror(r)); - closesocket(sock); - TESTabort(); - } - - pthread_t thread_id; - pthread_attr_t attr; - int result; - struct tcp_func_prm *thread_prm; - - thread_prm = (struct tcp_func_prm *)malloc(sizeof(struct tcp_func_prm)); - if (!thread_prm) { - fprintf(stderr, "Error: Out of memory\n"); - closesocket(sock); - TESTabort(); - } - thread_prm->sock = sock; - - (void)pthread_attr_init(&attr); - (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - result = pthread_create(&thread_id, &attr, tcp_func, (void *)thread_prm); - (void)pthread_attr_destroy(&attr); - if (result != 0) { - r = errno; - fprintf(stderr, "Error: Cannot create thread [%s]\n", strerror(r)); - closesocket(sock); - TESTabort(); - } - - test_sleep(5); -} - - +#if defined(TEST_FUZZ1) static int -test_http_request(const char *server, - uint16_t port, - int use_ssl, - const char *uri) +test_civetweb_client(const char *server, + uint16_t port, + int use_ssl, + const char *uri) { /* Client var */ struct mg_connection *client; @@ -328,7 +199,7 @@ LLVMFuzzerTestOneInput_URI(const uint8_t *data, size_t size) if (call_count == 0) { memset(URI, 0, sizeof(URI)); - init_civetweb(); + civetweb_init(); } call_count++; @@ -339,15 +210,17 @@ LLVMFuzzerTestOneInput_URI(const uint8_t *data, size_t size) return 1; } - return test_http_request("127.0.0.1", PORT_NUM_HTTP, 0, URI); + return test_civetweb_client("127.0.0.1", PORT_NUM_HTTP, 0, URI); } +#endif +#if defined(TEST_FUZZ2) static int LLVMFuzzerTestOneInput_REQUEST(const uint8_t *data, size_t size) { if (call_count == 0) { - init_civetweb(); + civetweb_init(); } call_count++; @@ -373,7 +246,7 @@ LLVMFuzzerTestOneInput_REQUEST(const uint8_t *data, size_t size) char trash[1024]; r = send(sock, data, size, 0); - if (r != size) { + if (r != (int)size) { fprintf(stderr, "Warning: %i bytes sent (TODO: Repeat)\n", r); } @@ -390,6 +263,176 @@ LLVMFuzzerTestOneInput_REQUEST(const uint8_t *data, size_t size) max_data_read = data_read; printf("GOT data: %i\n", data_read); } + return 0; +} +#endif + +#endif // defined(TEST_FUZZ1) || defined(TEST_FUZZ2) + + +/********************************************************/ +/* Init mock server ... test with CivetWeb client */ +/********************************************************/ +#if defined(TEST_FUZZ3) + +struct tcp_func_prm { + SOCKET sock; +}; + +struct tRESPONSE { + char data[4096]; + size_t size; +} RESPONSE; + + +volatile int mock_server_stop_flag = 0; + +static void +mock_server_exit(void) +{ + printf("MOCK server exit\n"); + mock_server_stop_flag = 1; + test_sleep(5); +} + + +static void * +mock_server_thread(void *arg) +{ + char req[1024 * 16]; + SOCKET svr = (SOCKET)(-1); + + /* Get thread parameters and free arg */ + { + struct tcp_func_prm *ptcp_func_prm = (struct tcp_func_prm *)arg; + svr = ptcp_func_prm->sock; + free(arg); + } + + mock_server_stop_flag = 0; + printf("MOCK server ready, sock %i\n", svr); + +next_request: + while (!mock_server_stop_flag) { + struct sockaddr_in cliadr; + socklen_t adrlen = sizeof(cliadr); + int buf_filled = 0; + int req_ready = 0; + + memset(&cliadr, 0, sizeof(cliadr)); + + SOCKET cli = accept(svr, (struct sockaddr *)&cliadr, &adrlen); + + if (cli == -1) { + int er = errno; + fprintf(stderr, "Error: Accept failed [%s]\n", strerror(er)); + test_sleep(1); + goto next_request; + } + + /* Read request */ + do { + int r = + recv(cli, req + buf_filled, sizeof(req) - buf_filled - 1, 0); + if (r > 0) { + buf_filled += r; + req[buf_filled] = 0; + if (strstr(req, "\r\n\r\n") != NULL) { + req_ready = 1; + } + } else { + /* some error */ + int er = errno; + fprintf(stderr, "Error: Recv failed [%s]\n", strerror(er)); + test_sleep(1); + goto next_request; + } + } while (!req_ready); + + /* Request is complete here. + * Now send response */ + send(cli, RESPONSE.data, RESPONSE.size, MSG_NOSIGNAL); + + /* Close connection. */ + shutdown(cli, SHUT_RDWR); + closesocket(cli); + } + return 0; +} + + +static void +mock_server_init(void) +{ + int r; + int bind_success = 0; + SOCKET sock = socket(AF_INET, SOCK_STREAM, 6); + if (sock == -1) { + r = errno; + fprintf(stderr, "Error: Cannot create socket [%s]\n", strerror(r)); + TESTabort(); + } + + for (PORT_NUM_HTTP = 1024; PORT_NUM_HTTP != 0; PORT_NUM_HTTP++) { + struct sockaddr_in sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + sin.sin_port = htons(PORT_NUM_HTTP); + r = bind(sock, (struct sockaddr *)&sin, sizeof(sin)); + if (r == 0) { + bind_success = 1; + break; + } + r = errno; + fprintf(stderr, "Warning: Cannot bind [%s]\n", strerror(r)); + } + + if (!bind_success) { + fprintf(stderr, "Error: Cannot bind to any port\n"); + closesocket(sock); + TESTabort(); + } + + printf("MOCK server running on port %i\n", (int)PORT_NUM_HTTP); + + r = listen(sock, 128); + if (r != 0) { + r = errno; + fprintf(stderr, "Error: Cannot listen [%s]\n", strerror(r)); + closesocket(sock); + TESTabort(); + } + + pthread_t thread_id; + pthread_attr_t attr; + int result; + struct tcp_func_prm *thread_prm; + + thread_prm = (struct tcp_func_prm *)malloc(sizeof(struct tcp_func_prm)); + if (!thread_prm) { + fprintf(stderr, "Error: Out of memory\n"); + closesocket(sock); + TESTabort(); + } + thread_prm->sock = sock; + + (void)pthread_attr_init(&attr); + (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + result = pthread_create(&thread_id, + &attr, + mock_server_thread, + (void *)thread_prm); + (void)pthread_attr_destroy(&attr); + if (result != 0) { + r = errno; + fprintf(stderr, "Error: Cannot create thread [%s]\n", strerror(r)); + closesocket(sock); + TESTabort(); + } + + test_sleep(3); + atexit(mock_server_exit); } @@ -397,7 +440,7 @@ static int LLVMFuzzerTestOneInput_RESPONSE(const uint8_t *data, size_t size) { if (call_count == 0) { - init_tcp(); + mock_server_init(); } call_count++; @@ -422,13 +465,22 @@ LLVMFuzzerTestOneInput_RESPONSE(const uint8_t *data, size_t size) int r = mg_get_response(conn, errbuf, sizeof(errbuf), 1000); const struct mg_response_info *ri = mg_get_response_info(conn); + (void)r; + (void)ri; + mg_close_connection(conn); return 0; } +#endif // defined(TEST_FUZZ3) + +/********************************************************/ +/* MAIN for fuzztest */ +/********************************************************/ +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); +// warning: no previous prototype for function 'LLVMFuzzerTestOneInput' -/* MAIN for fuzztest */ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {