diff --git a/fuzzing/Makefile b/fuzzing/Makefile new file mode 100644 index 0000000..76bde88 --- /dev/null +++ b/fuzzing/Makefile @@ -0,0 +1,2 @@ +default: + clang++ -fsanitize=address,fuzzer -O3 WebSocket.cpp -o WebSocket diff --git a/fuzzing/README.md b/fuzzing/README.md new file mode 100644 index 0000000..64f20fc --- /dev/null +++ b/fuzzing/README.md @@ -0,0 +1,5 @@ +# Fuzz-testing of parsers + +Here we do coverage-based fuzzing of code responsible for parsing arbitrary network data. + +A secure web server must be capable of receiving mass amount of malicious input without showing signs of weakness. Test code is being bombarded with evolving random data, with fitness determined by coverage - the goal of seeking out as much of the program state space as possible. This is done while AddressSanitizer monitors the program for memory correctness. \ No newline at end of file diff --git a/fuzzing/WebSocket.cpp b/fuzzing/WebSocket.cpp new file mode 100644 index 0000000..151b018 --- /dev/null +++ b/fuzzing/WebSocket.cpp @@ -0,0 +1,59 @@ +/* This is a fuzz test of the websocket parser */ + +#define WIN32_EXPORT + +/* We test the websocket parser */ +#include "../src/WebSocketProtocol.h" + +/* We use this to pad the fuzz */ +char *padded = new char[1024 * 500]; + +struct Impl { + static bool refusePayloadLength(uint64_t length, uWS::WebSocketState *wState, void *s) { + + /* We need a limit */ + if (length > 16000) { + return true; + } + + /* Return ok */ + return false; + } + + static bool setCompressed(uWS::WebSocketState *wState, void *s) { + /* We support it */ + return true; + } + + static void forceClose(uWS::WebSocketState *wState, void *s) { + + } + + static bool handleFragment(char *data, size_t length, unsigned int remainingBytes, int opCode, bool fin, uWS::WebSocketState *webSocketState, void *s) { + + if (opCode == uWS::TEXT) { + if (!uWS::protocol::isValidUtf8((unsigned char *)data, length)) { + /* Return break */ + return true; + } + } else if (opCode == uWS::CLOSE) { + uWS::protocol::parseClosePayload((char *)data, length); + } + + /* Return ok */ + return false; + } +}; + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + + /* Pad the fuzz */ + uWS::WebSocketState state; + memcpy(padded + 32, data, size); + + /* Parse it */ + uWS::WebSocketProtocol::consume((char *)padded + 32, size, &state, nullptr); + + return 0; +} +