Add MockedEchoServer fuzz target, fix App capture of moving this
This commit is contained in:
+3
-2
@@ -1,10 +1,11 @@
|
||||
default:
|
||||
# Fuzzing is only available with clang++
|
||||
clang -DLIBUS_NO_SSL -c -O3 uSocketsMock.c
|
||||
clang++ -DUWS_NO_ZLIB -DLIBUS_NO_SSL -std=c++17 -fsanitize=undefined,fuzzer -O3 -I../src -I../uSockets/src uSocketsMock.o MockedHelloWorld.cpp -o MockedHelloWorld
|
||||
clang++ -DUWS_NO_ZLIB -DLIBUS_NO_SSL -std=c++17 -fsanitize=address,fuzzer -O3 -I../src -I../uSockets/src uSocketsMock.o MockedHelloWorld.cpp -o MockedHelloWorld
|
||||
clang++ -DUWS_NO_ZLIB -DLIBUS_NO_SSL -std=c++17 -fsanitize=address,fuzzer -O3 -I../src -I../uSockets/src uSocketsMock.o MockedEchoServer.cpp -o MockedEchoServer
|
||||
# Purely "unit tests"
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 WebSocket.cpp -o WebSocket
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 Http.cpp -o Http
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 Extensions.cpp -o Extensions
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 Handshake.cpp -o Handshake
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 PerMessageDeflate.cpp -o PerMessageDeflate -lz
|
||||
clang++ -std=c++17 -fsanitize=address,fuzzer -O3 PerMessageDeflate.cpp -o PerMessageDeflate -lz
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#include "App.h"
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
/* This function pushes data to the uSockets mock */
|
||||
extern "C" void us_loop_read_mocked_data(struct us_loop *loop, char *data, unsigned int size);
|
||||
|
||||
uWS::TemplatedApp<false> *app;
|
||||
us_listen_socket_t *listenSocket;
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
|
||||
/* ws->getUserData returns one of these */
|
||||
struct PerSocketData {
|
||||
int nothing;
|
||||
};
|
||||
|
||||
/* Very simple WebSocket echo server */
|
||||
app = new uWS::TemplatedApp<false>(uWS::App().ws<PerSocketData>("/*", {
|
||||
/* Settings */
|
||||
.compression = uWS::SHARED_COMPRESSOR,
|
||||
.maxPayloadLength = 16 * 1024,
|
||||
.idleTimeout = 10,
|
||||
/* Handlers */
|
||||
.open = [](auto *ws, auto *req) {
|
||||
|
||||
},
|
||||
.message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
|
||||
ws->send(message, opCode);
|
||||
},
|
||||
.drain = [](auto *ws) {
|
||||
/* Check getBufferedAmount here */
|
||||
},
|
||||
.ping = [](auto *ws) {
|
||||
|
||||
},
|
||||
.pong = [](auto *ws) {
|
||||
|
||||
},
|
||||
.close = [](auto *ws, int code, std::string_view message) {
|
||||
|
||||
}
|
||||
}).listen(9001, [](us_listen_socket_t *listenSocket) {
|
||||
if (listenSocket) {
|
||||
std::cout << "Listening on port " << 9001 << std::endl;
|
||||
::listenSocket = listenSocket;
|
||||
}
|
||||
}));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
us_loop_read_mocked_data((struct us_loop *) uWS::Loop::get(), (char *) makePadded(data, size), size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+68
-21
@@ -3,15 +3,24 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdalign.h>
|
||||
|
||||
struct us_loop_t {
|
||||
|
||||
/* We only support one listen socket */
|
||||
struct us_listen_socket_t *listen_socket;
|
||||
alignas(16) struct us_listen_socket_t *listen_socket;
|
||||
|
||||
/* The list of closed sockets */
|
||||
struct us_socket_t *close_list;
|
||||
};
|
||||
|
||||
struct us_loop_t *us_create_loop(void *hint, void (*wakeup_cb)(struct us_loop_t *loop), void (*pre_cb)(struct us_loop_t *loop), void (*post_cb)(struct us_loop_t *loop), unsigned int ext_size) {
|
||||
return (struct us_loop_t *) malloc(sizeof(struct us_loop_t) + ext_size);
|
||||
struct us_loop_t *loop = (struct us_loop_t *) malloc(sizeof(struct us_loop_t) + ext_size);
|
||||
|
||||
loop->listen_socket = 0;
|
||||
loop->close_list = 0;
|
||||
|
||||
return loop;
|
||||
}
|
||||
|
||||
void us_loop_free(struct us_loop_t *loop) {
|
||||
@@ -27,7 +36,7 @@ void us_loop_run(struct us_loop_t *loop) {
|
||||
}
|
||||
|
||||
struct us_socket_context_t {
|
||||
struct us_loop_t *loop;
|
||||
alignas(16) struct us_loop_t *loop;
|
||||
|
||||
struct us_socket_t *(*on_open)(struct us_socket_t *s, int is_client, char *ip, int ip_length);
|
||||
struct us_socket_t *(*on_close)(struct us_socket_t *s);
|
||||
@@ -42,10 +51,13 @@ struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *
|
||||
|
||||
socket_context->loop = loop;
|
||||
|
||||
//printf("us_create_socket_context: %p\n", socket_context);
|
||||
|
||||
return socket_context;
|
||||
}
|
||||
|
||||
void us_socket_context_free(int ssl, struct us_socket_context_t *context) {
|
||||
//printf("us_socket_context_free: %p\n", context);
|
||||
free(context);
|
||||
}
|
||||
|
||||
@@ -98,16 +110,18 @@ void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) {
|
||||
}
|
||||
|
||||
struct us_socket_t {
|
||||
struct us_socket_context_t *context;
|
||||
};
|
||||
alignas(16) struct us_socket_context_t *context;
|
||||
|
||||
/* For ubsan? */
|
||||
struct us_new_socket_t {
|
||||
struct us_socket_context_t *context;
|
||||
int closed;
|
||||
int shutdown;
|
||||
|
||||
//struct us_socket_t *next;
|
||||
};
|
||||
|
||||
struct us_socket_t *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size) {
|
||||
printf("us_socket_context_connect\n");
|
||||
//printf("us_socket_context_connect\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) {
|
||||
@@ -115,11 +129,23 @@ struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *co
|
||||
}
|
||||
|
||||
struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s, int ext_size) {
|
||||
printf("us_socket_context_adopt_socket\n");
|
||||
struct us_socket_t *new_s = (struct us_socket_t *) realloc(s, sizeof(struct us_socket_t) + ext_size);
|
||||
new_s->context = context;
|
||||
|
||||
//printf("us_socket_context_adopt_socket: %p till %p\n", s, new_s);
|
||||
//printf("new context is: %p\n", new_s->context);
|
||||
|
||||
return new_s;
|
||||
}
|
||||
|
||||
struct us_socket_context_t *us_create_child_socket_context(int ssl, struct us_socket_context_t *context, int context_ext_size) {
|
||||
printf("us_create_child_socket_context\n");
|
||||
/* We simply create a new context in this mock */
|
||||
struct us_socket_context_options_t options = {};
|
||||
struct us_socket_context_t *child_context = us_create_socket_context(ssl, context->loop, context_ext_size, options);
|
||||
|
||||
//printf("us_create_child_socket_context: %p\n", child_context);
|
||||
|
||||
return child_context;
|
||||
}
|
||||
|
||||
int us_socket_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more) {
|
||||
@@ -143,18 +169,30 @@ void us_socket_flush(int ssl, struct us_socket_t *s) {
|
||||
}
|
||||
|
||||
void us_socket_shutdown(int ssl, struct us_socket_t *s) {
|
||||
|
||||
s->shutdown = 1;
|
||||
}
|
||||
|
||||
int us_socket_is_shut_down(int ssl, struct us_socket_t *s) {
|
||||
return 0;
|
||||
|
||||
//printf("us_socket_is_shut_down: %d\n", s->shutdown);
|
||||
|
||||
return s->shutdown;
|
||||
}
|
||||
|
||||
int us_socket_is_closed(int ssl, struct us_socket_t *s) {
|
||||
return 0;
|
||||
|
||||
//printf("us_socket_is_closed: %d\n", s->closed);
|
||||
|
||||
return s->closed;
|
||||
}
|
||||
|
||||
struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s) {
|
||||
s->closed = 1;
|
||||
|
||||
//printf("us_socket_close\n");
|
||||
|
||||
/* Add us to the close list */
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -165,21 +203,30 @@ void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *le
|
||||
/* We expose this function to let fuzz targets push data to uSockets */
|
||||
void us_loop_read_mocked_data(struct us_loop_t *loop, char *data, unsigned int size) {
|
||||
|
||||
//printf("us_loop_read_mocked_data\n");
|
||||
|
||||
/* We are unwound so let's free all closed polls here */
|
||||
|
||||
|
||||
/* We have one listen socket */
|
||||
int socket_ext_size = loop->listen_socket->socket_ext_size;
|
||||
|
||||
/* Create a socket with information from the listen socket */
|
||||
struct us_socket_t *s = (struct us_socket_t *) malloc(sizeof(struct us_socket_t) + socket_ext_size);
|
||||
s->context = loop->listen_socket->context;
|
||||
s->closed = 0;
|
||||
s->shutdown = 0;
|
||||
|
||||
/* Emit open event */
|
||||
s->context->on_open(s, 0, 0, 0);
|
||||
|
||||
/* Emit a bunch of data events here */
|
||||
s->context->on_data(s, data, size);
|
||||
|
||||
/* Emit close event */
|
||||
s->context->on_close(s);
|
||||
s = s->context->on_open(s, 0, 0, 0);
|
||||
if (!us_socket_is_closed(0, s)) {
|
||||
/* Emit a bunch of data events here */
|
||||
s = s->context->on_data(s, data, size);
|
||||
if (!us_socket_is_closed(0, s)) {
|
||||
/* Emit close event */
|
||||
s = s->context->on_close(s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the socket */
|
||||
free(s);
|
||||
|
||||
@@ -135,7 +135,8 @@ public:
|
||||
webSocketContext->getExt()->maxPayloadLength = behavior.maxPayloadLength;
|
||||
webSocketContext->getExt()->idleTimeout = behavior.idleTimeout;
|
||||
|
||||
return std::move(get(pattern, [webSocketContext, this, behavior = std::move(behavior)](auto *res, auto *req) mutable {
|
||||
return std::move(get(pattern, [webSocketContext, httpContext = this->httpContext, behavior = std::move(behavior)](auto *res, auto *req) mutable {
|
||||
|
||||
/* If we have this header set, it's a websocket */
|
||||
std::string_view secWebSocketKey = req->getHeader("sec-websocket-key");
|
||||
if (secWebSocketKey.length() == 24) {
|
||||
|
||||
Reference in New Issue
Block a user