LibFuzzer is in-process, coverage-guided, evolutionary fuzzing engine.
LibFuzzer is linked with the library under test, and feeds fuzzed inputs to
the library via a specific fuzzing entrypoint (aka "target function"); the
fuzzer then tracks which areas of the code are reached, and generates
mutations on the corpus of input data in order to maximize the code coverage.
Lets use libFuzzer to fuzz multipart_parser for the start.
Ref: https://llvm.org/docs/LibFuzzer.html
Signed-off-by: Petr Štetiar <ynezz@true.cz>
ADD_EXECUTABLE(cgi-io main.c)
TARGET_LINK_LIBRARIES(cgi-io cgi-lib ${ubox} ${ubus})
+IF(UNIT_TESTING)
+ ENABLE_TESTING()
+ ADD_SUBDIRECTORY(tests)
+ENDIF()
INSTALL(TARGETS cgi-io RUNTIME DESTINATION sbin)
--- /dev/null
+IF(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+ ADD_SUBDIRECTORY(fuzz-multipart-parser)
+ENDIF()
--- /dev/null
+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 -dict=${CMAKE_CURRENT_SOURCE_DIR}/dict/parser.dict ${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)
--- /dev/null
+"Content-Disposition: form-data; name="
+"\x0D\x0A"
+"\x0D"
+"x0A"
+"="
+";"
+"--"
+"Content-Type:"
+"filename="
+"--12--34--56"
--- /dev/null
+--AaB03x
+Content-Disposition: form-data; name="files"; filename="fi;le1.txt"
+Content-Type: text/plain
+
+contents
+--AaB03x--
\ No newline at end of file
--- /dev/null
+--AaB03x
+Content-Disposition: form-data; name="submit-name"
+
+Larry
+--AaB03x
+Content-Disposition: form-data; name="files"; filename="file1.txt"
+Content-Type: text/plain
+
+
+--AaB03x--
--- /dev/null
+#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 "multipart_parser.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *input, size_t size)
+{
+ char *buf = NULL;
+ multipart_parser *p;
+ static multipart_parser_settings s = {
+ .on_part_data = NULL,
+ .on_headers_complete = NULL,
+ .on_part_data_end = NULL,
+ .on_header_field = NULL,
+ .on_header_value = NULL,
+ };
+ buf = calloc(1, size + 1);
+ if (!buf)
+ return 0;
+
+ memcpy(buf, input, size);
+ p = multipart_parser_init(buf, &s);
+ if (!p) {
+ free(buf);
+ return 0;
+ }
+
+ multipart_parser_execute(p, buf, size + 1);
+ multipart_parser_free(p);
+ free(buf);
+
+ return 0;
+}