[PATCH cgi-io 06/12] Add fuzzing of utility functions
Petr Štetiar
ynezz at true.cz
Mon Oct 12 08:37:12 EDT 2020
Thus increase fuzzing coverage.
Signed-off-by: Petr Štetiar <ynezz at true.cz>
---
tests/CMakeLists.txt | 1 +
tests/fuzz/CMakeLists.txt | 18 ++++
.../58668e7669fd564d99db5d581fcdb6a5618440b5 | 1 +
.../5ba93c9db0cff93f52b521d7420e43f6eda2784f | Bin 0 -> 1 bytes
.../adc83b19e793491b1c6ea0fd8b46cd9f32e592fc | 1 +
tests/fuzz/test-fuzz.c | 43 +++++++++
util.c | 84 ++++++++++--------
util.h | 1 +
8 files changed, 112 insertions(+), 37 deletions(-)
create mode 100644 tests/fuzz/CMakeLists.txt
create mode 100644 tests/fuzz/corpus/58668e7669fd564d99db5d581fcdb6a5618440b5
create mode 100644 tests/fuzz/corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f
create mode 100644 tests/fuzz/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
create mode 100644 tests/fuzz/test-fuzz.c
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 8bb2a59412da..efad20642dd6 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,3 +1,4 @@
IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_SUBDIRECTORY(fuzz)
ADD_SUBDIRECTORY(fuzz-multipart-parser)
ENDIF()
diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt
new file mode 100644
index 000000000000..b4df45ca7b9b
--- /dev/null
+++ b/tests/fuzz/CMakeLists.txt
@@ -0,0 +1,18 @@
+FILE(GLOB test_cases "test-*.c")
+
+MACRO(ADD_FUZZER_TEST name)
+ ADD_EXECUTABLE(${name} ${name}.c)
+ TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR})
+ TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined)
+ TARGET_LINK_LIBRARIES(${name} cgi-lib)
+ ADD_TEST(
+ NAME ${name}
+ COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus
+ )
+ENDMACRO(ADD_FUZZER_TEST)
+
+FOREACH(test_case ${test_cases})
+ GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE)
+ ADD_FUZZER_TEST(${test_case})
+ENDFOREACH(test_case)
diff --git a/tests/fuzz/corpus/58668e7669fd564d99db5d581fcdb6a5618440b5 b/tests/fuzz/corpus/58668e7669fd564d99db5d581fcdb6a5618440b5
new file mode 100644
index 000000000000..22aac29bb31b
--- /dev/null
+++ b/tests/fuzz/corpus/58668e7669fd564d99db5d581fcdb6a5618440b5
@@ -0,0 +1 @@
+J
\ No newline at end of file
diff --git a/tests/fuzz/corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f b/tests/fuzz/corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f
new file mode 100644
index 0000000000000000000000000000000000000000..f76dd238ade08917e6712764a16a22005a50573d
GIT binary patch
literal 1
IcmZPo000310RR91
literal 0
HcmV?d00001
diff --git a/tests/fuzz/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc b/tests/fuzz/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
new file mode 100644
index 000000000000..8b137891791f
--- /dev/null
+++ b/tests/fuzz/corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
@@ -0,0 +1 @@
+
diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c
new file mode 100644
index 000000000000..a62c32609979
--- /dev/null
+++ b/tests/fuzz/test-fuzz.c
@@ -0,0 +1,43 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "util.h"
+
+static void fuzz_parse_command(const char *buf)
+{
+ char **p = parse_command(buf);
+ if (p)
+ free(p);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *input, size_t size)
+{
+ char *p = NULL;
+ char *fields[] = { "sessionid", NULL, "path", NULL, "filename", NULL, "mimetype", NULL };
+ char *buf = calloc(1, size+1);
+ memcpy(buf, input, size);
+
+ urldecode(buf);
+ fuzz_parse_command(buf);
+ p = canonicalize_path(buf, size+1);
+ if (p)
+ free(p);
+
+ p = postdecode_fields(buf, size+1, fields, 4);
+ if (!p)
+ return 0;
+
+ free(buf);
+
+ return 0;
+}
diff --git a/util.c b/util.c
index 9eb7b485e5fa..e8627589b49a 100644
--- a/util.c
+++ b/util.c
@@ -5,6 +5,8 @@
#include <string.h>
#include <unistd.h>
+#include <stdio.h>
+
#include "util.h"
char **
@@ -80,12 +82,55 @@ parse_command(const char *cmdline)
return argv;
}
+char *
+postdecode_fields(char *postbuf, ssize_t len, char **fields, int n_fields)
+{
+ char *p;
+ int i, field, found = 0;
+
+ for (p = postbuf, i = 0; i <= len; i++)
+ {
+ if (postbuf[i] == '=')
+ {
+ postbuf[i] = 0;
+
+ for (field = 0; field < (n_fields * 2); field += 2)
+ {
+ if (!strcmp(p, fields[field]))
+ {
+ fields[field + 1] = postbuf + i + 1;
+ found++;
+ }
+ }
+ }
+ else if (postbuf[i] == '&' || postbuf[i] == '\0')
+ {
+ postbuf[i] = 0;
+
+ if (found >= n_fields)
+ break;
+
+ p = postbuf + i + 1;
+ }
+ }
+
+ for (field = 0; field < (n_fields * 2); field += 2)
+ {
+ if (!urldecode(fields[field + 1]))
+ {
+ free(postbuf);
+ return NULL;
+ }
+ }
+
+ return postbuf;
+}
+
char *
postdecode(char **fields, int n_fields)
{
const char *var;
char *p, *postbuf;
- int i, field, found = 0;
ssize_t len = 0, rlen = 0, content_length = 0;
var = getenv("CONTENT_TYPE");
@@ -124,42 +169,7 @@ postdecode(char **fields, int n_fields)
return NULL;
}
- for (p = postbuf, i = 0; i <= len; i++)
- {
- if (postbuf[i] == '=')
- {
- postbuf[i] = 0;
-
- for (field = 0; field < (n_fields * 2); field += 2)
- {
- if (!strcmp(p, fields[field]))
- {
- fields[field + 1] = postbuf + i + 1;
- found++;
- }
- }
- }
- else if (postbuf[i] == '&' || postbuf[i] == '\0')
- {
- postbuf[i] = 0;
-
- if (found >= n_fields)
- break;
-
- p = postbuf + i + 1;
- }
- }
-
- for (field = 0; field < (n_fields * 2); field += 2)
- {
- if (!urldecode(fields[field + 1]))
- {
- free(postbuf);
- return NULL;
- }
- }
-
- return postbuf;
+ return postdecode_fields(postbuf, len, fields, n_fields);
}
char *
diff --git a/util.h b/util.h
index 0001195df38a..ecffe6c2bd73 100644
--- a/util.h
+++ b/util.h
@@ -6,6 +6,7 @@
char** parse_command(const char *cmdline);
char* postdecode(char **fields, int n_fields);
+char* postdecode_fields(char *postbuf, ssize_t len, char **fields, int n_fields);
char* canonicalize_path(const char *path, size_t len);
bool urldecode(char *buf);
char* datadup(const void *in, size_t len);
More information about the openwrt-devel
mailing list