From 52927697c19547fde9609ec388b129c0b9e85fc3 Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Wed, 17 Feb 2021 19:12:45 +0100 Subject: [PATCH] Port remaining mocks to libEpollFuzzer --- fuzzing/EpollEchoServer.cpp | 157 ++++++++++++++++++++++++++++++++++++ fuzzing/EpollHelloWorld.cpp | 5 +- fuzzing/Makefile | 2 + 3 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 fuzzing/EpollEchoServer.cpp diff --git a/fuzzing/EpollEchoServer.cpp b/fuzzing/EpollEchoServer.cpp new file mode 100644 index 0000000..d301411 --- /dev/null +++ b/fuzzing/EpollEchoServer.cpp @@ -0,0 +1,157 @@ +/* We rely on wrapped syscalls */ +#include "libEpollFuzzer/epoll_fuzzer.h" + +#include "App.h" + +/* We keep this one for teardown later on */ +struct us_listen_socket_t *listen_socket; + +/* This test is run by libEpollFuzzer */ +void test() { + + struct PerSocketData { + int nothing; + std::shared_ptr valid; + }; + + /* First byte determines what compressor to use */ + unsigned char compressorByte; + if (consume_byte(&compressorByte)) { + //uWS::Loop::get()->free(); + return; + } + + uWS::CompressOptions compressors[] = { + uWS::DISABLED, + uWS::SHARED_COMPRESSOR, + uWS::DEDICATED_COMPRESSOR_3KB, + uWS::DEDICATED_COMPRESSOR_4KB, + uWS::DEDICATED_COMPRESSOR_8KB, + uWS::DEDICATED_COMPRESSOR_16KB, + uWS::DEDICATED_COMPRESSOR_32KB, + uWS::DEDICATED_COMPRESSOR_64KB, + uWS::DEDICATED_COMPRESSOR_128KB, + uWS::DEDICATED_COMPRESSOR_256KB + }; + + uWS::CompressOptions compressor = compressors[compressorByte % 10]; + + { + auto app = uWS::App().ws("/broadcast", { + /* Settings */ + .compression = compressor, + /* We want this to be low so that we can hit it, yet bigger than 256 */ + .maxPayloadLength = 300, + .idleTimeout = 12, + /* Handlers */ + .open = [](auto *ws) { + /* Subscribe to anything */ + ws->subscribe(/*req->getHeader(*/"topic"/*)*/); + }, + .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { + if (message.length() && message[0] == 'C') { + ws->close(); + } else if (message.length() && message[0] == 'E') { + ws->end(1006); + } else { + /* Publish to topic sent by message */ + ws->publish(message, message, opCode, true); + + if (message.length() && message[0] == 'U') { + ws->unsubscribe(message); + } + } + }, + .drain = [](auto *ws) { + /* Check getBufferedAmount here */ + }, + .ping = [](auto *ws) { + + }, + .pong = [](auto *ws) { + + }, + .close = [](auto *ws, int code, std::string_view message) { + /* Not necessary but we'll call it for coverage */ + ws->unsubscribeAll(); + } + }).ws("/*", { + /* Settings */ + .compression = compressor, + /* We want this to be low so that we can hit it, yet bigger than 256 */ + .maxPayloadLength = 300, + .idleTimeout = 12, + /* Handlers */ + .open = [](auto *ws) { + + PerSocketData *psd = (PerSocketData *) ws->getUserData(); + psd->valid.reset(new bool{true}); + + //if (req->getHeader("close_me").length()) { + // ws->close(); + //} else if (req->getHeader("end_me").length()) { + // ws->end(1006); + //} + }, + .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { + if (message.length() > 300) { + /* Inform the sanitizer of the fault */ + fprintf(stderr, "Too long message passed\n"); + free((void *) -1); + } + + if (message.length() && message[0] == 'C') { + ws->close(); + } else if (message.length() && message[0] == 'E') { + ws->end(1006); + } else { + ws->send(message, opCode, true); + } + }, + .drain = [](auto *ws) { + /* Check getBufferedAmount here */ + }, + .ping = [](auto *ws) { + /* Here we test send and end while uncorked, by having them send from deferred */ + PerSocketData *psd = (PerSocketData *) ws->getUserData(); + + uWS::Loop::get()->defer([ws, valid = psd->valid]() { + if (valid.get()) { + /* We haven't been closed */ + ws->send("Hello!", uWS::TEXT, false); + ws->end(1000); + } + }); + }, + .pong = [](auto *ws) { + + }, + .close = [](auto *ws, int code, std::string_view message) { + + } + }).listen(9001, [](us_listen_socket_t *listenSocket) { + listen_socket = listenSocket; + }); + + app.run(); + } + + uWS::Loop::get()->free(); +} + +/* Thus function should shutdown the event-loop and let the test fall through */ +void teardown() { + /* If we are called twice there's a bug (it potentially could if + * all open sockets cannot be error-closed in one epoll_wait call). + * But we only allow 1k FDs and we have a buffer of 1024 from epoll_wait */ + if (!listen_socket) { + exit(-1); + } + + /* We might have open sockets still, and these will be error-closed by epoll_wait */ + // us_socket_context_close - close all open sockets created with this socket context + if (listen_socket) { + us_listen_socket_close(0, listen_socket); + listen_socket = NULL; + } +} diff --git a/fuzzing/EpollHelloWorld.cpp b/fuzzing/EpollHelloWorld.cpp index bca5c2c..16bcb92 100644 --- a/fuzzing/EpollHelloWorld.cpp +++ b/fuzzing/EpollHelloWorld.cpp @@ -82,8 +82,8 @@ void test() { }, .ping = [](auto *ws) { /* We use this to trigger the async/wakeup feature */ - uWS::Loop::get()->defer([]() { - /* Do nothing */ + uWS::Loop::get()->defer([]() { + /* Do nothing */ }); }, .pong = [](auto *ws) { @@ -101,6 +101,7 @@ void test() { /* This function is stupid */ us_loop_iteration_number(loop); struct us_socket_context_t *client_context = us_create_socket_context(0, loop, 0, {}); + us_socket_context_timestamp(0, client_context); client = us_socket_context_connect(0, client_context, "hostname", 5000, "localhost", 0, 0); us_socket_context_on_connect_error(0, client_context, [](struct us_socket_t *s, int code) { diff --git a/fuzzing/Makefile b/fuzzing/Makefile index 381f2a2..7a8704f 100644 --- a/fuzzing/Makefile +++ b/fuzzing/Makefile @@ -21,6 +21,8 @@ oss-fuzz: $(CC) $(CFLAGS) -DLIBUS_NO_SSL -std=c11 -I../uSockets/src -O3 -c ../uSockets/src/*.c ../uSockets/src/eventing/*.c ../uSockets/src/crypto/*.c # Link against object files $(CXX) $(CXXFLAGS) $(WRAPPED_SYSCALLS) -std=c++17 -O2 -DUWS_NO_ZLIB -I../src -I../uSockets/src EpollHelloWorld.cpp -o $(OUT)/EpollHelloWorld $(LIB_FUZZING_ENGINE) *.o + rm -f EpollHelloWorld.o + $(CXX) $(CXXFLAGS) $(WRAPPED_SYSCALLS) -std=c++17 -O2 -DUWS_NO_ZLIB -I../src -I../uSockets/src EpollEchoServer.cpp -o $(OUT)/EpollEchoServer $(LIB_FUZZING_ENGINE) *.o # "Unit tests" $(CXX) $(CXXFLAGS) -std=c++17 -O3 Extensions.cpp -o $(OUT)/Extensions $(LIB_FUZZING_ENGINE) $(CXX) $(CXXFLAGS) -std=c++17 -O3 QueryParser.cpp -o $(OUT)/QueryParser $(LIB_FUZZING_ENGINE)