/src/libgit2/deps/llhttp/api.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <stdlib.h> |
2 | | #include <stdio.h> |
3 | | #include <string.h> |
4 | | |
5 | | #include "llhttp.h" |
6 | | |
7 | | #define CALLBACK_MAYBE(PARSER, NAME) \ |
8 | 0 | do { \ |
9 | 0 | const llhttp_settings_t* settings; \ |
10 | 0 | settings = (const llhttp_settings_t*) (PARSER)->settings; \ |
11 | 0 | if (settings == NULL || settings->NAME == NULL) { \ |
12 | 0 | err = 0; \ |
13 | 0 | break; \ |
14 | 0 | } \ |
15 | 0 | err = settings->NAME((PARSER)); \ |
16 | 0 | } while (0) |
17 | | |
18 | | #define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ |
19 | 0 | do { \ |
20 | 0 | const llhttp_settings_t* settings; \ |
21 | 0 | settings = (const llhttp_settings_t*) (PARSER)->settings; \ |
22 | 0 | if (settings == NULL || settings->NAME == NULL) { \ |
23 | 0 | err = 0; \ |
24 | 0 | break; \ |
25 | 0 | } \ |
26 | 0 | err = settings->NAME((PARSER), (START), (LEN)); \ |
27 | 0 | if (err == -1) { \ |
28 | 0 | err = HPE_USER; \ |
29 | 0 | llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \ |
30 | 0 | } \ |
31 | 0 | } while (0) |
32 | | |
33 | | void llhttp_init(llhttp_t* parser, llhttp_type_t type, |
34 | 0 | const llhttp_settings_t* settings) { |
35 | 0 | llhttp__internal_init(parser); |
36 | |
|
37 | 0 | parser->type = type; |
38 | 0 | parser->settings = (void*) settings; |
39 | 0 | } |
40 | | |
41 | | |
42 | | #if defined(__wasm__) |
43 | | |
44 | | extern int wasm_on_message_begin(llhttp_t * p); |
45 | | extern int wasm_on_url(llhttp_t* p, const char* at, size_t length); |
46 | | extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); |
47 | | extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); |
48 | | extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); |
49 | | extern int wasm_on_headers_complete(llhttp_t * p, int status_code, |
50 | | uint8_t upgrade, int should_keep_alive); |
51 | | extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); |
52 | | extern int wasm_on_message_complete(llhttp_t * p); |
53 | | |
54 | | static int wasm_on_headers_complete_wrap(llhttp_t* p) { |
55 | | return wasm_on_headers_complete(p, p->status_code, p->upgrade, |
56 | | llhttp_should_keep_alive(p)); |
57 | | } |
58 | | |
59 | | const llhttp_settings_t wasm_settings = { |
60 | | wasm_on_message_begin, |
61 | | wasm_on_url, |
62 | | wasm_on_status, |
63 | | NULL, |
64 | | NULL, |
65 | | wasm_on_header_field, |
66 | | wasm_on_header_value, |
67 | | NULL, |
68 | | NULL, |
69 | | wasm_on_headers_complete_wrap, |
70 | | wasm_on_body, |
71 | | wasm_on_message_complete, |
72 | | NULL, |
73 | | NULL, |
74 | | NULL, |
75 | | NULL, |
76 | | NULL, |
77 | | NULL, |
78 | | NULL, |
79 | | NULL, |
80 | | NULL, |
81 | | NULL, |
82 | | NULL, |
83 | | }; |
84 | | |
85 | | |
86 | | llhttp_t* llhttp_alloc(llhttp_type_t type) { |
87 | | llhttp_t* parser = malloc(sizeof(llhttp_t)); |
88 | | llhttp_init(parser, type, &wasm_settings); |
89 | | return parser; |
90 | | } |
91 | | |
92 | | void llhttp_free(llhttp_t* parser) { |
93 | | free(parser); |
94 | | } |
95 | | |
96 | | #endif /* defined(__wasm__) */ |
97 | | |
98 | | /* Some getters required to get stuff from the parser */ |
99 | | |
100 | 0 | uint8_t llhttp_get_type(llhttp_t* parser) { |
101 | 0 | return parser->type; |
102 | 0 | } |
103 | | |
104 | 0 | uint8_t llhttp_get_http_major(llhttp_t* parser) { |
105 | 0 | return parser->http_major; |
106 | 0 | } |
107 | | |
108 | 0 | uint8_t llhttp_get_http_minor(llhttp_t* parser) { |
109 | 0 | return parser->http_minor; |
110 | 0 | } |
111 | | |
112 | 0 | uint8_t llhttp_get_method(llhttp_t* parser) { |
113 | 0 | return parser->method; |
114 | 0 | } |
115 | | |
116 | 0 | int llhttp_get_status_code(llhttp_t* parser) { |
117 | 0 | return parser->status_code; |
118 | 0 | } |
119 | | |
120 | 0 | uint8_t llhttp_get_upgrade(llhttp_t* parser) { |
121 | 0 | return parser->upgrade; |
122 | 0 | } |
123 | | |
124 | | |
125 | 0 | void llhttp_reset(llhttp_t* parser) { |
126 | 0 | llhttp_type_t type = parser->type; |
127 | 0 | const llhttp_settings_t* settings = parser->settings; |
128 | 0 | void* data = parser->data; |
129 | 0 | uint16_t lenient_flags = parser->lenient_flags; |
130 | |
|
131 | 0 | llhttp__internal_init(parser); |
132 | |
|
133 | 0 | parser->type = type; |
134 | 0 | parser->settings = (void*) settings; |
135 | 0 | parser->data = data; |
136 | 0 | parser->lenient_flags = lenient_flags; |
137 | 0 | } |
138 | | |
139 | | |
140 | 0 | llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) { |
141 | 0 | return llhttp__internal_execute(parser, data, data + len); |
142 | 0 | } |
143 | | |
144 | | |
145 | 0 | void llhttp_settings_init(llhttp_settings_t* settings) { |
146 | 0 | memset(settings, 0, sizeof(*settings)); |
147 | 0 | } |
148 | | |
149 | | |
150 | 0 | llhttp_errno_t llhttp_finish(llhttp_t* parser) { |
151 | 0 | int err; |
152 | | |
153 | | /* We're in an error state. Don't bother doing anything. */ |
154 | 0 | if (parser->error != 0) { |
155 | 0 | return 0; |
156 | 0 | } |
157 | | |
158 | 0 | switch (parser->finish) { |
159 | 0 | case HTTP_FINISH_SAFE_WITH_CB: |
160 | 0 | CALLBACK_MAYBE(parser, on_message_complete); |
161 | 0 | if (err != HPE_OK) return err; |
162 | | |
163 | | /* FALLTHROUGH */ |
164 | 0 | case HTTP_FINISH_SAFE: |
165 | 0 | return HPE_OK; |
166 | 0 | case HTTP_FINISH_UNSAFE: |
167 | 0 | parser->reason = "Invalid EOF state"; |
168 | 0 | return HPE_INVALID_EOF_STATE; |
169 | 0 | default: |
170 | 0 | abort(); |
171 | 0 | } |
172 | 0 | } |
173 | | |
174 | | |
175 | 0 | void llhttp_pause(llhttp_t* parser) { |
176 | 0 | if (parser->error != HPE_OK) { |
177 | 0 | return; |
178 | 0 | } |
179 | | |
180 | 0 | parser->error = HPE_PAUSED; |
181 | 0 | parser->reason = "Paused"; |
182 | 0 | } |
183 | | |
184 | | |
185 | 0 | void llhttp_resume(llhttp_t* parser) { |
186 | 0 | if (parser->error != HPE_PAUSED) { |
187 | 0 | return; |
188 | 0 | } |
189 | | |
190 | 0 | parser->error = 0; |
191 | 0 | } |
192 | | |
193 | | |
194 | 0 | void llhttp_resume_after_upgrade(llhttp_t* parser) { |
195 | 0 | if (parser->error != HPE_PAUSED_UPGRADE) { |
196 | 0 | return; |
197 | 0 | } |
198 | | |
199 | 0 | parser->error = 0; |
200 | 0 | } |
201 | | |
202 | | |
203 | 0 | llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) { |
204 | 0 | return parser->error; |
205 | 0 | } |
206 | | |
207 | | |
208 | 0 | const char* llhttp_get_error_reason(const llhttp_t* parser) { |
209 | 0 | return parser->reason; |
210 | 0 | } |
211 | | |
212 | | |
213 | 0 | void llhttp_set_error_reason(llhttp_t* parser, const char* reason) { |
214 | 0 | parser->reason = reason; |
215 | 0 | } |
216 | | |
217 | | |
218 | 0 | const char* llhttp_get_error_pos(const llhttp_t* parser) { |
219 | 0 | return parser->error_pos; |
220 | 0 | } |
221 | | |
222 | | |
223 | 0 | const char* llhttp_errno_name(llhttp_errno_t err) { |
224 | 0 | #define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME; |
225 | 0 | switch (err) { |
226 | 0 | HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) |
227 | 0 | default: abort(); |
228 | 0 | } |
229 | 0 | #undef HTTP_ERRNO_GEN |
230 | 0 | } |
231 | | |
232 | | |
233 | 0 | const char* llhttp_method_name(llhttp_method_t method) { |
234 | 0 | #define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING; |
235 | 0 | switch (method) { |
236 | 0 | HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN) |
237 | 0 | default: abort(); |
238 | 0 | } |
239 | 0 | #undef HTTP_METHOD_GEN |
240 | 0 | } |
241 | | |
242 | 0 | const char* llhttp_status_name(llhttp_status_t status) { |
243 | 0 | #define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING; |
244 | 0 | switch (status) { |
245 | 0 | HTTP_STATUS_MAP(HTTP_STATUS_GEN) |
246 | 0 | default: abort(); |
247 | 0 | } |
248 | 0 | #undef HTTP_STATUS_GEN |
249 | 0 | } |
250 | | |
251 | | |
252 | 0 | void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { |
253 | 0 | if (enabled) { |
254 | 0 | parser->lenient_flags |= LENIENT_HEADERS; |
255 | 0 | } else { |
256 | 0 | parser->lenient_flags &= ~LENIENT_HEADERS; |
257 | 0 | } |
258 | 0 | } |
259 | | |
260 | | |
261 | 0 | void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { |
262 | 0 | if (enabled) { |
263 | 0 | parser->lenient_flags |= LENIENT_CHUNKED_LENGTH; |
264 | 0 | } else { |
265 | 0 | parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH; |
266 | 0 | } |
267 | 0 | } |
268 | | |
269 | | |
270 | 0 | void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) { |
271 | 0 | if (enabled) { |
272 | 0 | parser->lenient_flags |= LENIENT_KEEP_ALIVE; |
273 | 0 | } else { |
274 | 0 | parser->lenient_flags &= ~LENIENT_KEEP_ALIVE; |
275 | 0 | } |
276 | 0 | } |
277 | | |
278 | 0 | void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) { |
279 | 0 | if (enabled) { |
280 | 0 | parser->lenient_flags |= LENIENT_TRANSFER_ENCODING; |
281 | 0 | } else { |
282 | 0 | parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING; |
283 | 0 | } |
284 | 0 | } |
285 | | |
286 | 0 | void llhttp_set_lenient_version(llhttp_t* parser, int enabled) { |
287 | 0 | if (enabled) { |
288 | 0 | parser->lenient_flags |= LENIENT_VERSION; |
289 | 0 | } else { |
290 | 0 | parser->lenient_flags &= ~LENIENT_VERSION; |
291 | 0 | } |
292 | 0 | } |
293 | | |
294 | 0 | void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) { |
295 | 0 | if (enabled) { |
296 | 0 | parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE; |
297 | 0 | } else { |
298 | 0 | parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE; |
299 | 0 | } |
300 | 0 | } |
301 | | |
302 | 0 | void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) { |
303 | 0 | if (enabled) { |
304 | 0 | parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR; |
305 | 0 | } else { |
306 | 0 | parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR; |
307 | 0 | } |
308 | 0 | } |
309 | | |
310 | 0 | void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) { |
311 | 0 | if (enabled) { |
312 | 0 | parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; |
313 | 0 | } else { |
314 | 0 | parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK; |
315 | 0 | } |
316 | 0 | } |
317 | | |
318 | 0 | void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) { |
319 | 0 | if (enabled) { |
320 | 0 | parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF; |
321 | 0 | } else { |
322 | 0 | parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF; |
323 | 0 | } |
324 | 0 | } |
325 | | |
326 | 0 | void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) { |
327 | 0 | if (enabled) { |
328 | 0 | parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE; |
329 | 0 | } else { |
330 | 0 | parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE; |
331 | 0 | } |
332 | 0 | } |
333 | | |
334 | | /* Callbacks */ |
335 | | |
336 | | |
337 | 0 | int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) { |
338 | 0 | int err; |
339 | 0 | CALLBACK_MAYBE(s, on_message_begin); |
340 | 0 | return err; |
341 | 0 | } |
342 | | |
343 | | |
344 | 0 | int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) { |
345 | 0 | int err; |
346 | 0 | SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p); |
347 | 0 | return err; |
348 | 0 | } |
349 | | |
350 | | |
351 | 0 | int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) { |
352 | 0 | int err; |
353 | 0 | CALLBACK_MAYBE(s, on_url_complete); |
354 | 0 | return err; |
355 | 0 | } |
356 | | |
357 | | |
358 | 0 | int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) { |
359 | 0 | int err; |
360 | 0 | SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p); |
361 | 0 | return err; |
362 | 0 | } |
363 | | |
364 | | |
365 | 0 | int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) { |
366 | 0 | int err; |
367 | 0 | CALLBACK_MAYBE(s, on_status_complete); |
368 | 0 | return err; |
369 | 0 | } |
370 | | |
371 | | |
372 | 0 | int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) { |
373 | 0 | int err; |
374 | 0 | SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p); |
375 | 0 | return err; |
376 | 0 | } |
377 | | |
378 | | |
379 | 0 | int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) { |
380 | 0 | int err; |
381 | 0 | CALLBACK_MAYBE(s, on_method_complete); |
382 | 0 | return err; |
383 | 0 | } |
384 | | |
385 | | |
386 | 0 | int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) { |
387 | 0 | int err; |
388 | 0 | SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p); |
389 | 0 | return err; |
390 | 0 | } |
391 | | |
392 | | |
393 | 0 | int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) { |
394 | 0 | int err; |
395 | 0 | CALLBACK_MAYBE(s, on_version_complete); |
396 | 0 | return err; |
397 | 0 | } |
398 | | |
399 | | |
400 | 0 | int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) { |
401 | 0 | int err; |
402 | 0 | SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p); |
403 | 0 | return err; |
404 | 0 | } |
405 | | |
406 | | |
407 | 0 | int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) { |
408 | 0 | int err; |
409 | 0 | CALLBACK_MAYBE(s, on_header_field_complete); |
410 | 0 | return err; |
411 | 0 | } |
412 | | |
413 | | |
414 | 0 | int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) { |
415 | 0 | int err; |
416 | 0 | SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p); |
417 | 0 | return err; |
418 | 0 | } |
419 | | |
420 | | |
421 | 0 | int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) { |
422 | 0 | int err; |
423 | 0 | CALLBACK_MAYBE(s, on_header_value_complete); |
424 | 0 | return err; |
425 | 0 | } |
426 | | |
427 | | |
428 | 0 | int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) { |
429 | 0 | int err; |
430 | 0 | CALLBACK_MAYBE(s, on_headers_complete); |
431 | 0 | return err; |
432 | 0 | } |
433 | | |
434 | | |
435 | 0 | int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) { |
436 | 0 | int err; |
437 | 0 | CALLBACK_MAYBE(s, on_message_complete); |
438 | 0 | return err; |
439 | 0 | } |
440 | | |
441 | | |
442 | 0 | int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) { |
443 | 0 | int err; |
444 | 0 | SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p); |
445 | 0 | return err; |
446 | 0 | } |
447 | | |
448 | | |
449 | 0 | int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { |
450 | 0 | int err; |
451 | 0 | CALLBACK_MAYBE(s, on_chunk_header); |
452 | 0 | return err; |
453 | 0 | } |
454 | | |
455 | | |
456 | 0 | int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) { |
457 | 0 | int err; |
458 | 0 | SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p); |
459 | 0 | return err; |
460 | 0 | } |
461 | | |
462 | | |
463 | 0 | int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) { |
464 | 0 | int err; |
465 | 0 | CALLBACK_MAYBE(s, on_chunk_extension_name_complete); |
466 | 0 | return err; |
467 | 0 | } |
468 | | |
469 | | |
470 | 0 | int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) { |
471 | 0 | int err; |
472 | 0 | SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p); |
473 | 0 | return err; |
474 | 0 | } |
475 | | |
476 | | |
477 | 0 | int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) { |
478 | 0 | int err; |
479 | 0 | CALLBACK_MAYBE(s, on_chunk_extension_value_complete); |
480 | 0 | return err; |
481 | 0 | } |
482 | | |
483 | | |
484 | 0 | int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { |
485 | 0 | int err; |
486 | 0 | CALLBACK_MAYBE(s, on_chunk_complete); |
487 | 0 | return err; |
488 | 0 | } |
489 | | |
490 | | |
491 | 0 | int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) { |
492 | 0 | int err; |
493 | 0 | CALLBACK_MAYBE(s, on_reset); |
494 | 0 | return err; |
495 | 0 | } |
496 | | |
497 | | |
498 | | /* Private */ |
499 | | |
500 | | |
501 | | void llhttp__debug(llhttp_t* s, const char* p, const char* endp, |
502 | 0 | const char* msg) { |
503 | 0 | if (p == endp) { |
504 | 0 | fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type, |
505 | 0 | s->flags, msg); |
506 | 0 | } else { |
507 | 0 | fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s, |
508 | 0 | s->type, s->flags, *p, msg); |
509 | 0 | } |
510 | 0 | } |