/src/mongoose/test/fuzz.c
Line | Count | Source |
1 | | #define MG_ENABLE_SOCKET 0 |
2 | | #define MG_ENABLE_LOG 0 |
3 | | #define MG_ENABLE_LINES 1 |
4 | | #define MG_ENABLE_TCPIP 1 |
5 | 3.23k | #define MG_IO_SIZE (4 * 1024 * 1024) // 4M IO size, unless resize is too slow |
6 | | |
7 | | #include "mongoose.c" |
8 | | |
9 | | #include "driver_mock.c" |
10 | | |
11 | | #ifdef __cplusplus |
12 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *, size_t); |
13 | | #else |
14 | | int LLVMFuzzerTestOneInput(const uint8_t *, size_t); |
15 | | #endif |
16 | | |
17 | 606k | static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { |
18 | 606k | struct mg_http_serve_opts opts = {.root_dir = "."}; |
19 | 606k | if (ev == MG_EV_HTTP_MSG) { |
20 | 296k | mg_http_serve_dir(c, (struct mg_http_message *) ev_data, &opts); |
21 | 296k | } |
22 | 606k | (void) fn_data; |
23 | 606k | } |
24 | | |
25 | 3.23k | int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
26 | 3.23k | mg_log_set(MG_LL_NONE); |
27 | | |
28 | 3.23k | struct mg_dns_message dm; |
29 | 3.23k | mg_dns_parse(data, size, &dm); |
30 | 3.23k | mg_dns_parse(NULL, 0, &dm); |
31 | | |
32 | 3.23k | struct mg_http_message hm; |
33 | 3.23k | if (mg_http_parse((const char *) data, size, &hm) > 0) { |
34 | 1.34k | mg_crc32(0, hm.method.ptr, hm.method.len); |
35 | 1.34k | mg_crc32(0, hm.uri.ptr, hm.uri.len); |
36 | 1.34k | mg_crc32(0, hm.uri.ptr, hm.uri.len); |
37 | 41.7k | for (size_t i = 0; i < sizeof(hm.headers) / sizeof(hm.headers[0]); i++) { |
38 | 40.3k | struct mg_str *k = &hm.headers[i].name, *v = &hm.headers[i].value; |
39 | 40.3k | mg_crc32(0, k->ptr, k->len); |
40 | 40.3k | mg_crc32(0, v->ptr, v->len); |
41 | 40.3k | } |
42 | 1.34k | } |
43 | 3.23k | mg_http_parse(NULL, 0, &hm); |
44 | | |
45 | 3.23k | struct mg_str body = mg_str_n((const char *) data, size); |
46 | 3.23k | char tmp[256]; |
47 | 3.23k | mg_http_get_var(&body, "key", tmp, sizeof(tmp)); |
48 | 3.23k | mg_http_get_var(&body, "key", NULL, 0); |
49 | 3.23k | mg_url_decode((char *) data, size, tmp, sizeof(tmp), 1); |
50 | 3.23k | mg_url_decode((char *) data, size, tmp, 1, 1); |
51 | 3.23k | mg_url_decode(NULL, 0, tmp, 1, 1); |
52 | | |
53 | 3.23k | struct mg_mqtt_message mm; |
54 | 3.23k | if (mg_mqtt_parse(data, size, 0, &mm) == MQTT_OK) { |
55 | 1.34k | mg_crc32(0, mm.topic.ptr, mm.topic.len); |
56 | 1.34k | mg_crc32(0, mm.data.ptr, mm.data.len); |
57 | 1.34k | mg_crc32(0, mm.dgram.ptr, mm.dgram.len); |
58 | 1.34k | } |
59 | 3.23k | mg_mqtt_parse(NULL, 0, 0, &mm); |
60 | 3.23k | if (mg_mqtt_parse(data, size, 5, &mm) == MQTT_OK) { |
61 | 1.33k | mg_crc32(0, mm.topic.ptr, mm.topic.len); |
62 | 1.33k | mg_crc32(0, mm.data.ptr, mm.data.len); |
63 | 1.33k | mg_crc32(0, mm.dgram.ptr, mm.dgram.len); |
64 | 1.33k | } |
65 | 3.23k | mg_mqtt_parse(NULL, 0, 5, &mm); |
66 | | |
67 | 3.23k | mg_sntp_parse(data, size); |
68 | 3.23k | mg_sntp_parse(NULL, 0); |
69 | | |
70 | 3.23k | char buf[size * 4 / 3 + 5]; // At least 4 chars and nul termination |
71 | 3.23k | mg_base64_decode((char *) data, size, buf, sizeof(buf)); |
72 | 3.23k | mg_base64_decode(NULL, 0, buf, sizeof(buf)); |
73 | 3.23k | mg_base64_encode(data, size, buf, sizeof(buf)); |
74 | 3.23k | mg_base64_encode(NULL, 0, buf, sizeof(buf)); |
75 | | |
76 | 3.23k | mg_globmatch((char *) data, size, (char *) data, size); |
77 | | |
78 | 3.23k | struct mg_str k, v, s = mg_str_n((char *) data, size); |
79 | 693k | while (mg_commalist(&s, &k, &v)) k.len = v.len = 0; |
80 | | |
81 | 3.23k | int n; |
82 | 3.23k | mg_json_get(mg_str_n((char *) data, size), "$", &n); |
83 | 3.23k | mg_json_get(mg_str_n((char *) data, size), "$.a.b", &n); |
84 | 3.23k | mg_json_get(mg_str_n((char *) data, size), "$[0]", &n); |
85 | | |
86 | 3.23k | if (size > 0) { |
87 | 3.23k | struct mg_tcpip_if mif = {.ip = 0x01020304, |
88 | 3.23k | .mask = 255, |
89 | 3.23k | .gw = 0x01010101, |
90 | 3.23k | .driver = &mg_tcpip_driver_mock}; |
91 | 3.23k | struct mg_mgr mgr; |
92 | 3.23k | mg_mgr_init(&mgr); |
93 | 3.23k | mg_tcpip_init(&mgr, &mif); |
94 | | |
95 | | // Make a copy of the random data, in order to modify it |
96 | 3.23k | void *pkt = malloc(size); |
97 | 3.23k | struct eth *eth = (struct eth *) pkt; |
98 | 3.23k | memcpy(pkt, data, size); |
99 | 3.23k | if (size > sizeof(*eth)) { |
100 | 2.19k | static size_t i; |
101 | 2.19k | uint16_t eth_types[] = {0x800, 0x800, 0x806, 0x86dd}; |
102 | 2.19k | memcpy(eth->dst, mif.mac, 6); // Set valid destination MAC |
103 | 2.19k | eth->type = mg_htons(eth_types[i++]); |
104 | 2.19k | if (i >= sizeof(eth_types) / sizeof(eth_types[0])) i = 0; |
105 | 2.19k | } |
106 | | |
107 | 3.23k | mg_tcpip_rx(&mif, pkt, size); |
108 | | |
109 | | // Test HTTP serving |
110 | 3.23k | const char *url = "http://localhost:12345"; |
111 | 3.23k | struct mg_connection *c = mg_http_connect(&mgr, url, fn, NULL); |
112 | 3.23k | mg_iobuf_add(&c->recv, 0, data, size); |
113 | 3.23k | c->pfn(c, MG_EV_READ, NULL, NULL); |
114 | | |
115 | 3.23k | mg_mgr_free(&mgr); |
116 | 3.23k | free(pkt); |
117 | 3.23k | mg_tcpip_free(&mif); |
118 | 3.23k | } |
119 | | |
120 | 3.23k | return 0; |
121 | 3.23k | } |
122 | | |
123 | | #if defined(MAIN) |
124 | | int main(int argc, char *argv[]) { |
125 | | int res = EXIT_FAILURE; |
126 | | if (argc > 1) { |
127 | | size_t len = 0; |
128 | | char *buf = mg_file_read(&mg_fs_posix, argv[1], &len); |
129 | | if (buf != NULL) { |
130 | | LLVMFuzzerTestOneInput((uint8_t *) buf, len); |
131 | | res = EXIT_SUCCESS; |
132 | | } |
133 | | free(buf); |
134 | | } |
135 | | return res; |
136 | | } |
137 | | #endif |