/src/unit/fuzzing/nxt_basic_fuzz.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) NGINX, Inc. |
3 | | */ |
4 | | |
5 | | #include <nxt_main.h> |
6 | | #include <nxt_sha1.h> |
7 | | #include <nxt_websocket.h> |
8 | | #include <nxt_websocket_header.h> |
9 | | |
10 | | /* DO NOT TRY THIS AT HOME! */ |
11 | | #include <nxt_websocket_accept.c> |
12 | | |
13 | | |
14 | 2.54k | #define KMININPUTLENGTH 4 |
15 | 1.26k | #define KMAXINPUTLENGTH 128 |
16 | | |
17 | | |
18 | | extern int LLVMFuzzerInitialize(int *argc, char ***argv); |
19 | | extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); |
20 | | |
21 | | void nxt_base64_fuzz(const u_char *data, size_t size); |
22 | | void nxt_djb_hash_fuzz(const u_char *data, size_t size); |
23 | | void nxt_murmur_hash2_fuzz(const u_char *data, size_t size); |
24 | | void nxt_parse_fuzz(const u_char *data, size_t size); |
25 | | void nxt_sha1_fuzz(const u_char *data, size_t size); |
26 | | void nxt_sha1_update_fuzz(const u_char *data, size_t size); |
27 | | void nxt_term_fuzz(const u_char *data, size_t size); |
28 | | void nxt_time_fuzz(const u_char *data, size_t size); |
29 | | void nxt_uri_fuzz(const u_char *data, size_t size); |
30 | | void nxt_utf8_fuzz(const u_char *data, size_t size); |
31 | | void nxt_websocket_base64_fuzz(const u_char *data, size_t size); |
32 | | void nxt_websocket_frame_fuzz(const u_char *data, size_t size); |
33 | | |
34 | | |
35 | | extern char **environ; |
36 | | |
37 | | |
38 | | int |
39 | | LLVMFuzzerInitialize(int *argc, char ***argv) |
40 | 2 | { |
41 | 2 | if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { |
42 | 0 | return NXT_ERROR; |
43 | 0 | } |
44 | | |
45 | 2 | return 0; |
46 | 2 | } |
47 | | |
48 | | |
49 | | int |
50 | | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
51 | 1.27k | { |
52 | 1.27k | if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { |
53 | 31 | return 0; |
54 | 31 | } |
55 | | |
56 | 1.23k | nxt_base64_fuzz(data, size); |
57 | 1.23k | nxt_djb_hash_fuzz(data, size); |
58 | 1.23k | nxt_murmur_hash2_fuzz(data, size); |
59 | 1.23k | nxt_parse_fuzz(data, size); |
60 | 1.23k | nxt_sha1_fuzz(data, size); |
61 | 1.23k | nxt_sha1_update_fuzz(data, size); |
62 | 1.23k | nxt_term_fuzz(data, size); |
63 | 1.23k | nxt_time_fuzz(data, size); |
64 | 1.23k | nxt_uri_fuzz(data, size); |
65 | 1.23k | nxt_utf8_fuzz(data, size); |
66 | 1.23k | nxt_websocket_base64_fuzz(data, size); |
67 | 1.23k | nxt_websocket_frame_fuzz(data, size); |
68 | | |
69 | 1.23k | return 0; |
70 | 1.27k | } |
71 | | |
72 | | |
73 | | void |
74 | | nxt_base64_fuzz(const u_char *data, size_t size) |
75 | 1.23k | { |
76 | 1.23k | u_char buf[256]; |
77 | 1.23k | ssize_t ret; |
78 | | |
79 | | /* |
80 | | * Validate base64 data before decoding. |
81 | | */ |
82 | 1.23k | ret = nxt_base64_decode(NULL, (u_char *)data, size); |
83 | 1.23k | if (ret == NXT_ERROR) { |
84 | 637 | return; |
85 | 637 | } |
86 | | |
87 | 602 | nxt_base64_decode(buf, (u_char *)data, size); |
88 | 602 | } |
89 | | |
90 | | |
91 | | void |
92 | | nxt_djb_hash_fuzz(const u_char *data, size_t size) |
93 | 1.23k | { |
94 | 1.23k | nxt_djb_hash(data, size); |
95 | 1.23k | nxt_djb_hash_lowcase(data, size); |
96 | 1.23k | } |
97 | | |
98 | | |
99 | | void |
100 | | nxt_murmur_hash2_fuzz(const u_char *data, size_t size) |
101 | 1.23k | { |
102 | 1.23k | nxt_murmur_hash2(data, size); |
103 | 1.23k | nxt_murmur_hash2_uint32(data); |
104 | 1.23k | } |
105 | | |
106 | | |
107 | | void |
108 | | nxt_parse_fuzz(const u_char *data, size_t size) |
109 | 1.23k | { |
110 | 1.23k | nxt_str_t input; |
111 | | |
112 | 1.23k | input.start = (u_char *)data; |
113 | 1.23k | input.length = size; |
114 | | |
115 | 1.23k | nxt_int_parse(data, size); |
116 | 1.23k | nxt_size_t_parse(data, size); |
117 | 1.23k | nxt_size_parse(data, size); |
118 | 1.23k | nxt_off_t_parse(data, size); |
119 | 1.23k | nxt_str_int_parse(&input); |
120 | 1.23k | nxt_number_parse(&data, data + size); |
121 | 1.23k | } |
122 | | |
123 | | |
124 | | void |
125 | | nxt_sha1_fuzz(const u_char *data, size_t size) |
126 | 1.23k | { |
127 | 1.23k | u_char bin_accept[20]; |
128 | 1.23k | nxt_sha1_t ctx; |
129 | | |
130 | 1.23k | nxt_sha1_init(&ctx); |
131 | 1.23k | nxt_sha1_update(&ctx, data, size); |
132 | 1.23k | nxt_sha1_final(bin_accept, &ctx); |
133 | 1.23k | } |
134 | | |
135 | | |
136 | | void |
137 | | nxt_sha1_update_fuzz(const u_char *data, size_t size) |
138 | 1.23k | { |
139 | 1.23k | u_char bin_accept[20]; |
140 | 1.23k | nxt_sha1_t ctx; |
141 | | |
142 | 1.23k | nxt_sha1_init(&ctx); |
143 | 1.23k | nxt_sha1_update(&ctx, data, size); |
144 | 1.23k | nxt_sha1_update(&ctx, data, size); |
145 | 1.23k | nxt_sha1_final(bin_accept, &ctx); |
146 | 1.23k | } |
147 | | |
148 | | |
149 | | void |
150 | | nxt_term_fuzz(const u_char *data, size_t size) |
151 | 1.23k | { |
152 | 1.23k | nxt_term_parse(data, size, 0); |
153 | 1.23k | nxt_term_parse(data, size, 1); |
154 | 1.23k | } |
155 | | |
156 | | |
157 | | void |
158 | | nxt_time_fuzz(const u_char *data, size_t size) |
159 | 1.23k | { |
160 | 1.23k | nxt_time_parse(data, size); |
161 | 1.23k | } |
162 | | |
163 | | |
164 | | void |
165 | | nxt_uri_fuzz(const u_char *data, size_t size) |
166 | 1.23k | { |
167 | 1.23k | u_char *dst; |
168 | | |
169 | 1.23k | dst = nxt_zalloc(size * 3); |
170 | 1.23k | if (dst == NULL) { |
171 | 0 | return; |
172 | 0 | } |
173 | | |
174 | 1.23k | nxt_decode_uri(dst, (u_char *)data, size); |
175 | 1.23k | nxt_decode_uri_plus(dst, (u_char *)data, size); |
176 | | |
177 | 1.23k | nxt_memzero(dst, size * 3); |
178 | 1.23k | nxt_encode_uri(NULL, (u_char *)data, size); |
179 | 1.23k | nxt_encode_uri(dst, (u_char *)data, size); |
180 | | |
181 | 1.23k | nxt_free(dst); |
182 | 1.23k | } |
183 | | |
184 | | |
185 | | void |
186 | | nxt_utf8_fuzz(const u_char *data, size_t size) |
187 | 1.23k | { |
188 | 1.23k | const u_char *in; |
189 | | |
190 | 1.23k | in = data; |
191 | 1.23k | nxt_utf8_decode(&in, data + size); |
192 | | |
193 | 1.23k | nxt_utf8_casecmp((const u_char *)"ABC АБВ ΑΒΓ", |
194 | 1.23k | data, |
195 | 1.23k | nxt_length("ABC АБВ ΑΒΓ"), |
196 | 1.23k | size); |
197 | 1.23k | } |
198 | | |
199 | | |
200 | | void |
201 | | nxt_websocket_base64_fuzz(const u_char *data, size_t size) |
202 | 1.23k | { |
203 | 1.23k | u_char *out; |
204 | | |
205 | 1.23k | out = nxt_zalloc(size * 2); |
206 | 1.23k | if (out == NULL) { |
207 | 0 | return; |
208 | 0 | } |
209 | | |
210 | 1.23k | nxt_websocket_base64_encode(out, data, size); |
211 | | |
212 | 1.23k | nxt_free(out); |
213 | 1.23k | } |
214 | | |
215 | | |
216 | | void |
217 | | nxt_websocket_frame_fuzz(const u_char *data, size_t size) |
218 | 1.23k | { |
219 | 1.23k | u_char *input; |
220 | | |
221 | | /* |
222 | | * Resolve overwrites-const-input by using a copy of the data. |
223 | | */ |
224 | 1.23k | input = nxt_malloc(size); |
225 | 1.23k | if (input == NULL) { |
226 | 0 | return; |
227 | 0 | } |
228 | | |
229 | 1.23k | nxt_memcpy(input, data, size); |
230 | | |
231 | 1.23k | nxt_websocket_frame_init(input, 0); |
232 | 1.23k | nxt_websocket_frame_header_size(input); |
233 | 1.23k | nxt_websocket_frame_payload_len(input); |
234 | | |
235 | 1.23k | nxt_free(input); |
236 | 1.23k | } |