mirror of
https://github.com/cesanta/mongoose
synced 2026-08-25 22:26:06 -04:00
109 lines
2.8 KiB
C
109 lines
2.8 KiB
C
// https://llvm.org/docs/LibFuzzer.html
|
|
|
|
#define MG_ENABLE_SOCKET 1
|
|
#define MG_ENABLE_LOG 0
|
|
#define MG_ENABLE_LINES 1
|
|
#define MG_ENABLE_TCPIP 0
|
|
#define MG_IO_SIZE (1 * 1024 * 1024) // Big IO size for fast resizes
|
|
#define MG_TLS MG_TLS_BUILTIN
|
|
|
|
#include "mongoose.c"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
|
|
#else
|
|
int LLVMFuzzerTestOneInput(const uint8_t *, size_t);
|
|
#endif
|
|
|
|
// Preprocessor magic, just add/remove functions here and leave the rest alone
|
|
#define TABLE(_) \
|
|
_(mg_tls_server_recv_hello) \
|
|
_(mg_tls_server_recv_finish) \
|
|
_(mg_tls_client_recv_hello) \
|
|
_(mg_tls_client_recv_finish) \
|
|
_(mg_tls_client_recv_ext) \
|
|
_(mg_tls_recv_cert_verify) \
|
|
// ...
|
|
|
|
struct f {
|
|
int (*f)(struct mg_connection *);
|
|
const char *name;
|
|
};
|
|
|
|
struct f f_[] = {
|
|
#define ENTRY(func) { func, #func },
|
|
TABLE(ENTRY)
|
|
#undef ENTRY
|
|
};
|
|
// end of preprocessor magic
|
|
|
|
|
|
|
|
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|
struct mg_connection c_[sizeof(f_)/sizeof(struct f)], *c = &c_[0];
|
|
struct tls_data tls_[sizeof(f_)/sizeof(struct f)];
|
|
int i;
|
|
if (size == 0) return 0;
|
|
mg_log_set(MG_LL_INFO);
|
|
memset(c, 0, sizeof(*c));
|
|
c->send.align = c->recv.align = c->rtls.align = MG_IO_SIZE;
|
|
c->is_tls = c->is_tls_hs = 1;
|
|
for (i = 0; i < (int)(sizeof(f_)/sizeof(struct f)); i++) {
|
|
struct mg_iobuf *io;
|
|
c = &c_[i];
|
|
io = &c->rtls;
|
|
if (i > 0) memcpy(c, &c_[0], sizeof(*c)); // copy from 1st one
|
|
if (i > 1) c->is_client = 1; // from 2 on, client functions
|
|
memset(&tls_[i], 0, sizeof(struct tls_data));
|
|
if (io->size - io->len < size && !mg_iobuf_resize(io, io->len + size)) {
|
|
mg_error(c, "oom");
|
|
return 0; // drop it
|
|
}
|
|
memcpy(&io->buf[io->len], data, size);
|
|
io->len += size;
|
|
c->tls = &tls_[i];
|
|
#ifdef PRINT_FUNCNAME
|
|
printf("CALLING %s\n", f_[i].name);
|
|
#endif
|
|
f_[i].f(c);
|
|
mg_iobuf_free(io);
|
|
}
|
|
|
|
// mg_tls_recv_cert() has an extra bool parameter
|
|
c = &c_[0]; // reuse first one
|
|
c->tls = &tls_[0];
|
|
for (i = 0; i < 2; i++) {
|
|
struct mg_iobuf *io;
|
|
io = &c->rtls;
|
|
c->is_client = (i > 0);
|
|
memset(c->tls, 0, sizeof(struct tls_data));
|
|
if (io->size - io->len < size && !mg_iobuf_resize(io, io->len + size)) {
|
|
mg_error(c, "oom");
|
|
return 0; // drop it
|
|
}
|
|
memcpy(&io->buf[io->len], data, size);
|
|
io->len += size;
|
|
#ifdef PRINT_FUNCNAME
|
|
printf("CALLING mg_tls_recv_cert\n");
|
|
#endif
|
|
mg_tls_recv_cert(c, !c->is_client); // call server for client and client for server
|
|
mg_iobuf_free(io);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#if defined(MAIN)
|
|
int main(int argc, char *argv[]) {
|
|
int res = EXIT_FAILURE;
|
|
if (argc > 1) {
|
|
struct mg_str data = mg_file_read(&mg_fs_posix, argv[1]);
|
|
if (data.buf != NULL) {
|
|
LLVMFuzzerTestOneInput((uint8_t *) data.buf, data.len);
|
|
res = EXIT_SUCCESS;
|
|
}
|
|
free(data.buf);
|
|
}
|
|
return res;
|
|
}
|
|
#endif
|