1 /* SPDX-License-Identifier: MIT */
2 
3 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
4  *
5  * Additional changes are licensed under the same terms as NGINX and
6  * copyright Joyent, Inc. and other Node contributors. All rights reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to
10  * deal in the Software without restriction, including without limitation the
11  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12  * sell copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24  * IN THE SOFTWARE.
25  */
26 #include <zephyr/net/http/parser.h>
27 #include <zephyr/sys/__assert.h>
28 #include <stddef.h>
29 #include <ctype.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <limits.h>
33 #include <zephyr/toolchain.h>
34 
35 #ifndef ULLONG_MAX
36 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
37 #endif
38 
39 #ifndef MIN
40 # define MIN(a, b) ((a) < (b) ? (a) : (b))
41 #endif
42 
43 #ifndef ARRAY_SIZE
44 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
45 #endif
46 
47 #ifndef BIT_AT
48 # define BIT_AT(a, i)                                                \
49 	(!!((unsigned int) (a)[(unsigned int) (i) >> 3] &                  \
50 	 (1 << ((unsigned int) (i) & 7))))
51 #endif
52 
53 #ifndef ELEM_AT
54 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
55 #endif
56 
57 #define SET_ERRNO(e)	(parser->http_errno = (e))
58 #define CURRENT_STATE() p_state
59 #define UPDATE_STATE(V) (p_state = (enum state)(V))
60 
61 #ifdef __GNUC__
62 # define LIKELY(X) __builtin_expect(!!(X), 1)
63 # define UNLIKELY(X) __builtin_expect(!!(X), 0)
64 #else
65 # define LIKELY(X) (X)
66 # define UNLIKELY(X) (X)
67 #endif
68 
69 /* Set the mark FOR; non-destructive if mark is already set */
70 #define MARK(FOR)                                                          \
71 do {                                                                       \
72 	if (!FOR##_mark) {                                                 \
73 		FOR##_mark = p;                                            \
74 	}                                                                  \
75 } while (false)
76 
77 /* Don't allow the total size of the HTTP headers (including the status
78  * line) to exceed HTTP_MAX_HEADER_SIZE.  This check is here to protect
79  * embedders against denial-of-service attacks where the attacker feeds
80  * us a never-ending header that the embedder keeps buffering.
81  *
82  * This check is arguably the responsibility of embedders but we're doing
83  * it on the embedder's behalf because most won't bother and this way we
84  * make the web a little safer.  HTTP_MAX_HEADER_SIZE is still far bigger
85  * than any reasonable request or response so this should never affect
86  * day-to-day operation.
87  */
88 static inline
count_header_size(struct http_parser * parser,int bytes)89 int count_header_size(struct http_parser *parser, int bytes)
90 {
91 	parser->nread += bytes;
92 
93 	if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) {
94 		parser->http_errno = HPE_HEADER_OVERFLOW;
95 		return -1;
96 	}
97 
98 	return 0;
99 }
100 
101 #define PROXY_CONNECTION "proxy-connection"
102 #define CONNECTION "connection"
103 #define CONTENT "content-"
104 #define CONTENT_LENGTH "content-length"
105 #define CONTENT_RANGE "content-range"
106 #define TRANSFER_ENCODING "transfer-encoding"
107 #define UPGRADE "upgrade"
108 #define CHUNKED "chunked"
109 #define KEEP_ALIVE "keep-alive"
110 #define CLOSE "close"
111 
112 
113 static const
114 char *method_strings[] = {"DELETE", "GET", "HEAD", "POST", "PUT", "CONNECT",
115 			  "OPTIONS", "TRACE", "COPY", "LOCK", "MKCOL", "MOVE",
116 			  "PROPFIND", "PROPPATCH", "SEARCH", "UNLOCK", "BIND",
117 			  "REBIND", "UNBIND", "ACL", "REPORT", "MKACTIVITY",
118 			  "CHECKOUT", "MERGE", "M-SEARCH", "NOTIFY",
119 			  "SUBSCRIBE", "UNSUBSCRIBE", "PATCH", "PURGE",
120 			  "MKCALENDAR", "LINK", "UNLINK"};
121 
122 
123 /* Tokens as defined by rfc 2616. Also lowercases them.
124  *        token       = 1*<any CHAR except CTLs or separators>
125  *     separators     = "(" | ")" | "<" | ">" | "@"
126  *                    | "," | ";" | ":" | "\" | <">
127  *                    | "/" | "[" | "]" | "?" | "="
128  *                    | "{" | "}" | SP | HT
129  */
130 static const char tokens[256] = {
131 /*   0 nul    1 soh    2 stx    3 etx    4 eot    5 enq    6 ack    7 bel  */
132 	0,       0,       0,       0,       0,       0,       0,       0,
133 /*   8 bs     9 ht    10 nl    11 vt    12 np    13 cr    14 so    15 si   */
134 	0,       0,       0,       0,       0,       0,       0,       0,
135 /*  16 dle   17 dc1   18 dc2   19 dc3   20 dc4   21 nak   22 syn   23 etb */
136 	0,       0,       0,       0,       0,       0,       0,       0,
137 /*  24 can   25 em    26 sub   27 esc   28 fs    29 gs    30 rs    31 us  */
138 	0,       0,       0,       0,       0,       0,       0,       0,
139 /*  32 sp    33  !    34  "    35  #    36  $    37  %    38  &    39  '  */
140 	0,      '!',      0,      '#',     '$',     '%',     '&',    '\'',
141 /*  40  (    41  )    42  *    43  +    44  ,    45  -    46  .    47  /  */
142 	0,       0,      '*',     '+',      0,      '-',     '.',      0,
143 /*  48  0    49  1    50  2    51  3    52  4    53  5    54  6    55  7  */
144 	'0',     '1',     '2',     '3',     '4',     '5',     '6',     '7',
145 /*  56  8    57  9    58  :    59  ;    60  <    61  =    62  >    63  ?  */
146 	'8',     '9',      0,       0,       0,       0,       0,       0,
147 /*  64  @    65  A    66  B    67  C    68  D    69  E    70  F    71  G  */
148 	0,      'a',     'b',     'c',     'd',     'e',     'f',     'g',
149 /*  72  H    73  I    74  J    75  K    76  L    77  M    78  N    79  O  */
150 	'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
151 /*  80  P    81  Q    82  R    83  S    84  T    85  U    86  V    87  W  */
152 	'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
153 /*  88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _  */
154 	'x',     'y',     'z',      0,       0,       0,      '^',     '_',
155 /*  96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g  */
156 	'`',     'a',     'b',     'c',     'd',     'e',     'f',     'g',
157 /* 104  h   105  i   106  j   107  k   108  l   109  m   110  n   111  o  */
158 	'h',     'i',     'j',     'k',     'l',     'm',     'n',     'o',
159 /* 112  p   113  q   114  r   115  s   116  t   117  u   118  v   119  w  */
160 	'p',     'q',     'r',     's',     't',     'u',     'v',     'w',
161 /* 120  x   121  y   122  z   123  {   124  |   125  }   126  ~   127 del */
162 	'x',     'y',     'z',      0,      '|',      0,      '~',       0
163 };
164 
165 
166 static const
167 int8_t unhex[256] = {
168 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
169 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
170 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
171 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
172 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
173 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
174 	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
175 	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
176 };
177 
178 
179 #define PARSING_HEADER(state) (state <= s_headers_done)
180 
181 enum header_states {
182 	h_general = 0,
183 	h_C,
184 	h_CO,
185 	h_CON,
186 	h_matching_connection,
187 	h_matching_proxy_connection,
188 	h_matching_content,
189 	h_CONTENT_,
190 	h_matching_content_length,
191 	h_matching_content_range,
192 	h_matching_transfer_encoding,
193 	h_matching_upgrade,
194 	h_connection,
195 	h_content_length,
196 	h_content_range_start,
197 	h_content_range_end,
198 	h_content_range_total,
199 	h_transfer_encoding,
200 	h_upgrade,
201 	h_matching_transfer_encoding_chunked,
202 	h_matching_connection_token_start,
203 	h_matching_connection_keep_alive,
204 	h_matching_connection_close,
205 	h_matching_connection_upgrade,
206 	h_matching_connection_token,
207 	h_transfer_encoding_chunked,
208 	h_connection_keep_alive,
209 	h_connection_close,
210 	h_connection_upgrade
211 };
212 
213 static inline
cb_notify(struct http_parser * parser,enum state * current_state,http_cb cb,int cb_error,size_t * parsed,size_t already_parsed)214 int cb_notify(struct http_parser *parser, enum state *current_state, http_cb cb,
215 	      int cb_error, size_t *parsed, size_t already_parsed)
216 {
217 	__ASSERT_NO_MSG(HTTP_PARSER_ERRNO(parser) == HPE_OK);
218 
219 	if (cb == NULL) {
220 		return 0;
221 	}
222 
223 	parser->state = *current_state;
224 	if (UNLIKELY(cb(parser) != 0)) {
225 		SET_ERRNO(cb_error);
226 	}
227 	*current_state = parser->state;
228 	/* We either errored above or got paused; get out */
229 	if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {
230 		*parsed = already_parsed;
231 		return -HTTP_PARSER_ERRNO(parser);
232 	}
233 
234 	return 0;
235 }
236 
237 static inline
cb_data(struct http_parser * parser,http_data_cb cb,int cb_error,enum state * current_state,size_t * parsed,size_t already_parsed,const char ** mark,size_t len)238 int cb_data(struct http_parser *parser, http_data_cb cb, int cb_error,
239 	    enum state *current_state, size_t *parsed, size_t already_parsed,
240 	    const char **mark, size_t len)
241 {
242 	int rc;
243 
244 	__ASSERT_NO_MSG(HTTP_PARSER_ERRNO(parser) == HPE_OK);
245 	if (*mark == NULL) {
246 		return 0;
247 	}
248 	if (cb == NULL) {
249 		goto lb_end;
250 	}
251 
252 	parser->state = *current_state;
253 	rc = cb(parser, *mark, len);
254 	if (UNLIKELY(rc != 0)) {
255 		SET_ERRNO(cb_error);
256 	}
257 	*current_state = parser->state;
258 	/* We either errored above or got paused; get out */
259 	if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) {
260 		*parsed = already_parsed;
261 		return -HTTP_PARSER_ERRNO(parser);
262 	}
263 lb_end:
264 	*mark = NULL;
265 
266 	return 0;
267 }
268 
269 
270 /* Macros for character classes; depends on strict-mode  */
271 #define CR                  '\r'
272 #define LF                  '\n'
273 #define LOWER(c)            (unsigned char)(c | 0x20)
274 #define IS_ALPHA(c)         (LOWER(c) >= 'a' && LOWER(c) <= 'z')
275 #define IS_NUM(c)           ((c) >= '0' && (c) <= '9')
276 #define IS_ALPHANUM(c)      (IS_ALPHA(c) || IS_NUM(c))
277 #define IS_HEX(c)           (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
278 
279 #define IS_MARK(c)		((c) == '-' || (c) == '_' || (c) == '.' || \
280 				 (c) == '!' || (c) == '~' || (c) == '*' || \
281 				 (c) == '\'' || (c) == '(' || (c) == ')')
282 
283 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
284 				(c) == ';' || (c) == ':' || (c) == '&' ||  \
285 				(c) == '=' || (c) == '+' || (c) == '$' ||  \
286 				(c) == ',')
287 
288 #define STRICT_TOKEN(c)     (tokens[(unsigned char)c])
289 
290 #ifdef HTTP_PARSER_STRICT
291 #define TOKEN(c)            (tokens[(unsigned char)c])
292 #define IS_HOST_CHAR(c)     (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
293 #else
294 #define TOKEN(c)            ((c == ' ') ? ' ' : tokens[(unsigned char)c])
295 #define IS_HOST_CHAR(c)                                                        \
296 	(IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
297 #endif
298 
299 /**
300  * Verify that a char is a valid visible (printable) US-ASCII
301  * character or %x80-FF
302  **/
303 #define IS_HEADER_CHAR(ch)                                                     \
304 	(ch == CR || ch == LF || ch == 9 || \
305 	 ((unsigned char)ch > 31 && ch != 127))
306 
307 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
308 
309 
310 #ifdef HTTP_PARSER_STRICT
311 static inline
strict_check(struct http_parser * parser,int c)312 int strict_check(struct http_parser *parser, int c)
313 {
314 	if (c) {
315 		parser->http_errno = HPE_STRICT;
316 		return -1;
317 	}
318 	return 0;
319 }
320 
321 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
322 #else
323 static inline
strict_check(struct http_parser * parser,int c)324 int strict_check(struct http_parser *parser, int c)
325 {
326 	(void)parser;
327 	(void)c;
328 	return 0;
329 }
330 # define NEW_MESSAGE() start_state
331 #endif
332 
333 static struct {
334 	const char *name;
335 	const char *description;
336 } http_strerror_tab[] = {
337 	{"HPE_OK", "success"},
338 	{"HPE_CB_message_begin", "the on_message_begin callback failed"},
339 	{"HPE_CB_url", "the on_url callback failed"},
340 	{"HPE_CB_header_field", "the on_header_field callback failed"},
341 	{"HPE_CB_header_value", "the on_header_value callback failed"},
342 	{"HPE_CB_headers_complete", "the on_headers_complete callback failed"},
343 	{"HPE_CB_body", "the on_body callback failed"},
344 	{"HPE_CB_message_complete", "the on_message_complete callback failed"},
345 	{"HPE_CB_status", "the on_status callback failed"},
346 	{"HPE_CB_chunk_header", "the on_chunk_header callback failed"},
347 	{"HPE_CB_chunk_complete", "the on_chunk_complete callback failed"},
348 	{"HPE_INVALID_EOF_STATE", "stream ended at an unexpected time"},
349 	{"HPE_HEADER_OVERFLOW", "too many header bytes seen; "
350 				"overflow detected"},
351 	{"HPE_CLOSED_CONNECTION", "data received after completed connection: "
352 				  "close message"},
353 	{"HPE_INVALID_VERSION", "invalid HTTP version"},
354 	{"HPE_INVALID_STATUS", "invalid HTTP status code"},
355 	{"HPE_INVALID_METHOD", "invalid HTTP method"},
356 	{"HPE_INVALID_URL", "invalid URL"},
357 	{"HPE_INVALID_HOST", "invalid host"},
358 	{"HPE_INVALID_PORT", "invalid port"},
359 	{"HPE_INVALID_PATH", "invalid path"},
360 	{"HPE_INVALID_QUERY_STRING", "invalid query string"},
361 	{"HPE_INVALID_FRAGMENT", "invalid fragment"},
362 	{"HPE_LF_EXPECTED", "LF character expected"},
363 	{"HPE_INVALID_HEADER_TOKEN", "invalid character in header"},
364 	{"HPE_INVALID_CONTENT_LENGTH", "invalid character in content-length "
365 				       "header"},
366 	{"HPE_UNEXPECTED_CONTENT_LENGTH", "unexpected content-length header"},
367 	{"HPE_INVALID_CONTENT_RANGE", "invalid character in content-range header"},
368 	{"HPE_UNEXPECTED_CONTENT_RANGE", "unexpected content-range header"},
369 	{"HPE_INVALID_CHUNK_SIZE", "invalid character in chunk size header"},
370 	{"HPE_INVALID_CONSTANT", "invalid constant string"},
371 	{"HPE_INVALID_INTERNAL_STATE", "encountered unexpected internal state"},
372 	{"HPE_STRICT", "strict mode assertion failed"},
373 	{"HPE_PAUSED", "parser is paused"},
374 	{"HPE_UNKNOWN", "an unknown error occurred"}
375 };
376 
377 int http_message_needs_eof(const struct http_parser *parser);
378 
379 static
parser_header_state(struct http_parser * parser,char ch,char c)380 int parser_header_state(struct http_parser *parser, char ch, char c)
381 {
382 	int cond1;
383 
384 	switch (parser->header_state) {
385 	case h_general:
386 		break;
387 
388 	case h_C:
389 		parser->index++;
390 		parser->header_state = (c == 'o' ? h_CO : h_general);
391 		break;
392 
393 	case h_CO:
394 		parser->index++;
395 		parser->header_state = (c == 'n' ? h_CON : h_general);
396 		break;
397 
398 	case h_CON:
399 		parser->index++;
400 		switch (c) {
401 		case 'n':
402 			parser->header_state = h_matching_connection;
403 			break;
404 		case 't':
405 			parser->header_state = h_matching_content;
406 			break;
407 		default:
408 			parser->header_state = h_general;
409 			break;
410 		}
411 		break;
412 
413 	/* connection */
414 
415 	case h_matching_connection:
416 		parser->index++;
417 		cond1 = parser->index > sizeof(CONNECTION) - 1;
418 		if (cond1 || c != CONNECTION[parser->index]) {
419 			parser->header_state = h_general;
420 		} else if (parser->index == sizeof(CONNECTION) - 2) {
421 			parser->header_state = h_connection;
422 		}
423 		break;
424 
425 	/* proxy-connection */
426 
427 	case h_matching_proxy_connection:
428 		parser->index++;
429 		cond1 = parser->index > sizeof(PROXY_CONNECTION) - 1;
430 		if (cond1 || c != PROXY_CONNECTION[parser->index]) {
431 			parser->header_state = h_general;
432 		} else if (parser->index == sizeof(PROXY_CONNECTION) - 2) {
433 			parser->header_state = h_connection;
434 		}
435 		break;
436 
437 	/*content-length or content-range*/
438 
439 	case h_matching_content:
440 		parser->index++;
441 		cond1 = parser->index > sizeof(CONTENT) - 1;
442 		if (cond1 || c != CONTENT[parser->index]) {
443 			parser->header_state = h_general;
444 		} else if (parser->index == sizeof(CONTENT) - 2) {
445 			parser->header_state = h_CONTENT_;
446 		}
447 		break;
448 
449 	case h_CONTENT_:
450 		parser->index++;
451 		if (c == 'l') {
452 			parser->header_state = h_matching_content_length;
453 		} else if (c == 'r') {
454 			parser->header_state = h_matching_content_range;
455 		} else {
456 			parser->header_state = h_general;
457 		}
458 		break;
459 
460 
461 	case h_matching_content_length:
462 		parser->index++;
463 		cond1 = parser->index > sizeof(CONTENT_LENGTH) - 1;
464 		if (cond1 || c != CONTENT_LENGTH[parser->index]) {
465 			parser->header_state = h_general;
466 		} else if (parser->index == sizeof(CONTENT_LENGTH) - 2) {
467 			parser->header_state = h_content_length;
468 		}
469 		break;
470 
471 	case h_matching_content_range:
472 		parser->index++;
473 		cond1 = parser->index > sizeof(CONTENT_RANGE) - 1;
474 		if (cond1 || c != CONTENT_RANGE[parser->index]) {
475 			parser->header_state = h_general;
476 		} else if (parser->index == sizeof(CONTENT_RANGE) - 2) {
477 			parser->header_state = h_content_range_start;
478 		}
479 		break;
480 
481 	/* transfer-encoding */
482 
483 	case h_matching_transfer_encoding:
484 		parser->index++;
485 		cond1 = parser->index > sizeof(TRANSFER_ENCODING) - 1;
486 		if (cond1 || c != TRANSFER_ENCODING[parser->index]) {
487 			parser->header_state = h_general;
488 		} else if (parser->index == sizeof(TRANSFER_ENCODING) - 2) {
489 			parser->header_state = h_transfer_encoding;
490 		}
491 		break;
492 
493 	/* upgrade */
494 
495 	case h_matching_upgrade:
496 		parser->index++;
497 		cond1 = parser->index > sizeof(UPGRADE) - 1;
498 		if (cond1 || c != UPGRADE[parser->index]) {
499 			parser->header_state = h_general;
500 		} else if (parser->index == sizeof(UPGRADE) - 2) {
501 			parser->header_state = h_upgrade;
502 		}
503 		break;
504 
505 	case h_connection:
506 	case h_content_length:
507 	case h_content_range_start:
508 	case h_content_range_end:
509 	case h_content_range_total:
510 	case h_transfer_encoding:
511 	case h_upgrade:
512 		if (ch != ' ') {
513 			parser->header_state = h_general;
514 		}
515 		break;
516 
517 	default:
518 		__ASSERT_NO_MSG(0 && "Unknown header_state");
519 		break;
520 	}
521 	return 0;
522 }
523 
524 static
header_states(struct http_parser * parser,const char * data,size_t len,const char ** ptr,enum state * p_state,enum header_states * header_state,char ch,char c)525 int header_states(struct http_parser *parser, const char *data, size_t len,
526 		  const char **ptr, enum state *p_state,
527 		  enum header_states *header_state, char ch, char c)
528 {
529 	enum header_states h_state = *header_state;
530 	const char *p = *ptr;
531 	int cond1;
532 
533 	switch (h_state) {
534 	case h_general: {
535 		size_t limit = data + len - p;
536 		const char *p_cr;
537 		const char *p_lf;
538 
539 		limit = MIN(limit, HTTP_MAX_HEADER_SIZE);
540 		p_cr = (const char *)memchr(p, CR, limit);
541 		p_lf = (const char *)memchr(p, LF, limit);
542 		if (p_cr != NULL) {
543 			if (p_lf != NULL && p_cr >= p_lf) {
544 				p = p_lf;
545 			} else {
546 				p = p_cr;
547 			}
548 		} else if (UNLIKELY(p_lf != NULL)) {
549 			p = p_lf;
550 		} else {
551 			p = data + len;
552 		}
553 		--p;
554 
555 		break;
556 	}
557 
558 	case h_connection:
559 	case h_transfer_encoding:
560 		__ASSERT_NO_MSG(0 && "Shouldn't get here.");
561 		break;
562 
563 	case h_content_length: {
564 		uint64_t t;
565 		uint64_t value;
566 
567 		if (ch == ' ') {
568 			break;
569 		}
570 
571 		if (UNLIKELY(!IS_NUM(ch))) {
572 			SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
573 			parser->header_state = h_state;
574 			return -1;
575 		}
576 
577 		t = parser->content_length;
578 		t *= 10U;
579 		t += ch - '0';
580 
581 		/* Overflow? Test against a conservative limit for simplicity */
582 		value = (ULLONG_MAX - 10) / 10;
583 
584 		if (UNLIKELY(value < parser->content_length)) {
585 			SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
586 			parser->header_state = h_state;
587 			return -1;
588 		}
589 
590 		parser->content_length = t;
591 		break;
592 	}
593 
594 	case h_content_range_start: {
595 		uint64_t t;
596 		uint64_t value;
597 
598 		if (IS_ALPHA(ch)) {
599 			break;
600 		}
601 
602 		if (ch == ' ') {
603 			break;
604 		}
605 
606 		if (ch == '-' || ch == '*') {
607 			h_state = h_content_range_end;
608 			break;
609 		}
610 
611 		if (UNLIKELY(!IS_NUM(ch))) {
612 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
613 			parser->header_state = h_state;
614 			return -1;
615 		}
616 
617 		t = parser->content_range.start;
618 		t *= 10U;
619 		t += ch - '0';
620 
621 		/* Overflow? Test against a conservative limit for simplicity */
622 		value = (ULLONG_MAX - 10) / 10;
623 
624 		if (UNLIKELY(value < parser->content_range.start)) {
625 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
626 			parser->header_state = h_state;
627 			return -1;
628 		}
629 
630 		parser->content_range.start = t;
631 		break;
632 	}
633 
634 	case h_content_range_end: {
635 		uint64_t t;
636 		uint64_t value;
637 
638 		if (ch == ' ') {
639 			break;
640 		}
641 
642 		if (ch == '/') {
643 			h_state = h_content_range_total;
644 			break;
645 		}
646 
647 		if (UNLIKELY(!IS_NUM(ch))) {
648 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
649 			parser->header_state = h_state;
650 			return -1;
651 		}
652 
653 		t = parser->content_range.end;
654 		t *= 10U;
655 		t += ch - '0';
656 
657 		/* Overflow? Test against a conservative limit for simplicity */
658 		value = (ULLONG_MAX - 10) / 10;
659 
660 		if (UNLIKELY(value < parser->content_range.end)) {
661 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
662 			parser->header_state = h_state;
663 			return -1;
664 		}
665 
666 		parser->content_range.end = t;
667 		break;
668 	}
669 
670 	case h_content_range_total: {
671 		uint64_t t;
672 		uint64_t value;
673 
674 		if (ch == ' ') {
675 			break;
676 		}
677 
678 		if (ch == '*') {
679 			break;
680 		}
681 
682 		if (UNLIKELY(!IS_NUM(ch))) {
683 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
684 			parser->header_state = h_state;
685 			return -1;
686 		}
687 
688 		t = parser->content_range.total;
689 		t *= 10U;
690 		t += ch - '0';
691 
692 		/* Overflow? Test against a conservative limit for simplicity */
693 		value = (ULLONG_MAX - 10) / 10;
694 
695 		if (UNLIKELY(value < parser->content_range.total)) {
696 			SET_ERRNO(HPE_INVALID_CONTENT_RANGE);
697 			parser->header_state = h_state;
698 			return -1;
699 		}
700 
701 		parser->content_range.total = t;
702 		break;
703 	}
704 
705 	/* Transfer-Encoding: chunked */
706 	case h_matching_transfer_encoding_chunked:
707 		parser->index++;
708 		cond1 = parser->index > sizeof(CHUNKED) - 1;
709 		if (cond1 || c != CHUNKED[parser->index]) {
710 			h_state = h_general;
711 		} else if (parser->index == sizeof(CHUNKED) - 2) {
712 			h_state = h_transfer_encoding_chunked;
713 		}
714 		break;
715 
716 	case h_matching_connection_token_start:
717 		/* looking for 'Connection: keep-alive' */
718 		if (c == 'k') {
719 			h_state = h_matching_connection_keep_alive;
720 			/* looking for 'Connection: close' */
721 		} else if (c == 'c') {
722 			h_state = h_matching_connection_close;
723 		} else if (c == 'u') {
724 			h_state = h_matching_connection_upgrade;
725 		} else if (STRICT_TOKEN(c)) {
726 			h_state = h_matching_connection_token;
727 		} else if (c == ' ' || c == '\t') {
728 			/* Skip lws */
729 		} else {
730 			h_state = h_general;
731 		}
732 		break;
733 
734 	/* looking for 'Connection: keep-alive' */
735 	case h_matching_connection_keep_alive:
736 		parser->index++;
737 		cond1 = parser->index > sizeof(KEEP_ALIVE) - 1;
738 		if (cond1 || c != KEEP_ALIVE[parser->index]) {
739 			h_state = h_matching_connection_token;
740 		} else if (parser->index == sizeof(KEEP_ALIVE) - 2) {
741 			h_state = h_connection_keep_alive;
742 		}
743 		break;
744 
745 	/* looking for 'Connection: close' */
746 	case h_matching_connection_close:
747 		parser->index++;
748 		cond1 = parser->index > sizeof(CLOSE) - 1;
749 		if (cond1 || c != CLOSE[parser->index]) {
750 			h_state = h_matching_connection_token;
751 		} else if (parser->index == sizeof(CLOSE) - 2) {
752 			h_state = h_connection_close;
753 		}
754 		break;
755 
756 	/* looking for 'Connection: upgrade' */
757 	case h_matching_connection_upgrade:
758 		parser->index++;
759 		cond1 = parser->index > sizeof(UPGRADE) - 1;
760 		if (cond1 || c != UPGRADE[parser->index]) {
761 			h_state = h_matching_connection_token;
762 		} else if (parser->index == sizeof(UPGRADE) - 2) {
763 			h_state = h_connection_upgrade;
764 		}
765 		break;
766 
767 	case h_matching_connection_token:
768 		if (ch == ',') {
769 			h_state = h_matching_connection_token_start;
770 			parser->index = 0U;
771 		}
772 		break;
773 
774 	case h_transfer_encoding_chunked:
775 		if (ch != ' ') {
776 			h_state = h_general;
777 		}
778 		break;
779 
780 	case h_connection_keep_alive:
781 	case h_connection_close:
782 	case h_connection_upgrade:
783 		if (ch == ',') {
784 			if (h_state == h_connection_keep_alive) {
785 				parser->flags |= F_CONNECTION_KEEP_ALIVE;
786 			} else if (h_state == h_connection_close) {
787 				parser->flags |= F_CONNECTION_CLOSE;
788 			} else if (h_state == h_connection_upgrade) {
789 				parser->flags |= F_CONNECTION_UPGRADE;
790 			}
791 			h_state = h_matching_connection_token_start;
792 			parser->index = 0U;
793 		} else if (ch != ' ') {
794 			h_state = h_matching_connection_token;
795 		}
796 		break;
797 
798 	default:
799 		*p_state = s_header_value;
800 		h_state = h_general;
801 		break;
802 	}
803 
804 	*header_state = h_state;
805 	*ptr = p;
806 
807 	return 0;
808 }
809 
810 static
zero_content_length(struct http_parser * parser,const struct http_parser_settings * settings,enum state * current_state,size_t * parsed,const char * p,const char * data)811 int zero_content_length(struct http_parser *parser,
812 			const struct http_parser_settings *settings,
813 			enum state *current_state, size_t *parsed,
814 			const char *p, const char *data)
815 {
816 	enum state p_state = *current_state;
817 	int rc;
818 
819 	if (parser->content_length == 0U) {
820 		/* Content-Length header given but zero:
821 		 * Content-Length: 0\r\n
822 		 */
823 		UPDATE_STATE(NEW_MESSAGE());
824 
825 		rc = cb_notify(parser, &p_state, settings->on_message_complete,
826 			       HPE_CB_message_complete, parsed, p - data + 1);
827 		if (rc != 0) {
828 			return rc;
829 		}
830 
831 	} else if (parser->content_length != ULLONG_MAX) {
832 		/* Content-Length header given and
833 		 * non-zero
834 		 */
835 		UPDATE_STATE(s_body_identity);
836 	} else {
837 		if (!http_message_needs_eof(parser)) {
838 			/* Assume content-length 0 -
839 			 * read the next
840 			 */
841 			UPDATE_STATE(NEW_MESSAGE());
842 
843 			rc = cb_notify(parser, &p_state,
844 				       settings->on_message_complete,
845 				       HPE_CB_message_complete, parsed,
846 				       p - data + 1);
847 			if (rc != 0) {
848 				return rc;
849 			}
850 
851 		} else {
852 			/* Read body until EOF */
853 			UPDATE_STATE(s_body_identity_eof);
854 		}
855 	}
856 
857 	*current_state = p_state;
858 
859 	return 0;
860 }
861 
862 static
parser_execute(struct http_parser * parser,const struct http_parser_settings * settings,const char * data,size_t len,size_t * parsed)863 int parser_execute(struct http_parser *parser,
864 		   const struct http_parser_settings *settings,
865 		   const char *data, size_t len, size_t *parsed)
866 {
867 	const unsigned int lenient = parser->lenient_http_headers;
868 	enum state p_state = (enum state) parser->state;
869 	const char *p = data;
870 	const char *header_field_mark = 0;
871 	const char *header_value_mark = 0;
872 	const char *url_mark = 0;
873 	const char *body_mark = 0;
874 	const char *status_mark = 0;
875 	int8_t unhex_val;
876 	int rc;
877 	char ch;
878 	char c;
879 
880 	*parsed = 0;
881 
882 	/* We're in an error state. Don't bother doing anything. */
883 	if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
884 		return 0;
885 	}
886 
887 	if (len == 0) {
888 		switch (CURRENT_STATE()) {
889 		case s_body_identity_eof:
890 			/* Use of CALLBACK_NOTIFY() here would erroneously
891 			 * return 1 byte read if
892 			 * we got paused.
893 			 */
894 			cb_notify(parser, &p_state,
895 				  settings->on_message_complete,
896 				  HPE_CB_message_complete, parsed, p - data);
897 			return 0;
898 
899 		case s_dead:
900 		case s_start_req_or_res:
901 		case s_start_res:
902 		case s_start_req:
903 			return 0;
904 
905 		default:
906 			SET_ERRNO(HPE_INVALID_EOF_STATE);
907 			return 1;
908 		}
909 	}
910 
911 
912 	if (CURRENT_STATE() == s_header_field) {
913 		header_field_mark = data;
914 	}
915 	if (CURRENT_STATE() == s_header_value) {
916 		header_value_mark = data;
917 	}
918 	switch (CURRENT_STATE()) {
919 	case s_req_path:
920 	case s_req_schema:
921 	case s_req_schema_slash:
922 	case s_req_schema_slash_slash:
923 	case s_req_server_start:
924 	case s_req_server:
925 	case s_req_server_with_at:
926 	case s_req_query_string_start:
927 	case s_req_query_string:
928 	case s_req_fragment_start:
929 	case s_req_fragment:
930 		url_mark = data;
931 		break;
932 	case s_res_status:
933 		status_mark = data;
934 		break;
935 	default:
936 		break;
937 	}
938 
939 	for (p = data; p != data + len; p++) {
940 		ch = *p;
941 
942 		if (PARSING_HEADER(CURRENT_STATE())) {
943 			rc = count_header_size(parser, 1);
944 			if (rc != 0) {
945 				goto error;
946 			}
947 		}
948 
949 reexecute:
950 		switch (CURRENT_STATE()) {
951 
952 		case s_dead:
953 			/* this state is used after a 'Connection: close'
954 			 * message
955 			 * the parser will error out if it reads another message
956 			 */
957 			if (LIKELY(ch == CR || ch == LF)) {
958 				break;
959 			}
960 
961 			SET_ERRNO(HPE_CLOSED_CONNECTION);
962 			goto error;
963 
964 		case s_start_req_or_res: {
965 			if (ch == CR || ch == LF) {
966 				break;
967 			}
968 			parser->flags = 0U;
969 			parser->content_length = ULLONG_MAX;
970 			parser->content_range.start = 0U;
971 			parser->content_range.end = 0U;
972 			parser->content_range.total = 0U;
973 			parser->content_range_present = false;
974 
975 			if (ch == 'H') {
976 				UPDATE_STATE(s_res_or_resp_H);
977 
978 				rc = cb_notify(parser, &p_state,
979 					       settings->on_message_begin,
980 					       HPE_CB_message_begin,
981 					       parsed, p - data + 1);
982 				if (rc != 0) {
983 					return rc;
984 				}
985 			} else {
986 				parser->type = HTTP_REQUEST;
987 				UPDATE_STATE(s_start_req);
988 				goto reexecute;
989 			}
990 
991 			break;
992 		}
993 
994 		case s_res_or_resp_H:
995 			if (ch == 'T') {
996 				parser->type = HTTP_RESPONSE;
997 				UPDATE_STATE(s_res_HT);
998 			} else {
999 				if (UNLIKELY(ch != 'E')) {
1000 					SET_ERRNO(HPE_INVALID_CONSTANT);
1001 					goto error;
1002 				}
1003 
1004 				parser->type = HTTP_REQUEST;
1005 				parser->method = HTTP_HEAD;
1006 				parser->index = 2U;
1007 				UPDATE_STATE(s_req_method);
1008 			}
1009 			break;
1010 
1011 		case s_start_res: {
1012 			parser->flags = 0U;
1013 			parser->content_length = ULLONG_MAX;
1014 
1015 			switch (ch) {
1016 			case 'H':
1017 				UPDATE_STATE(s_res_H);
1018 				break;
1019 
1020 			case CR:
1021 			case LF:
1022 				break;
1023 
1024 			default:
1025 				SET_ERRNO(HPE_INVALID_CONSTANT);
1026 				goto error;
1027 			}
1028 
1029 
1030 			rc = cb_notify(parser, &p_state,
1031 				       settings->on_message_begin,
1032 				       HPE_CB_message_begin, parsed,
1033 				       p - data + 1);
1034 			if (rc != 0) {
1035 				return rc;
1036 			}
1037 			break;
1038 		}
1039 
1040 		case s_res_H:
1041 			rc = strict_check(parser, ch != 'T');
1042 			if (rc != 0) {
1043 				goto error;
1044 			}
1045 			UPDATE_STATE(s_res_HT);
1046 			break;
1047 
1048 		case s_res_HT:
1049 			rc = strict_check(parser, ch != 'T');
1050 			if (rc != 0) {
1051 				goto error;
1052 			}
1053 			UPDATE_STATE(s_res_HTT);
1054 			break;
1055 
1056 		case s_res_HTT:
1057 			rc = strict_check(parser, ch != 'P');
1058 			if (rc != 0) {
1059 				goto error;
1060 			}
1061 			UPDATE_STATE(s_res_HTTP);
1062 			break;
1063 
1064 		case s_res_HTTP:
1065 			rc = strict_check(parser, ch != '/');
1066 			if (rc != 0) {
1067 				goto error;
1068 			}
1069 			UPDATE_STATE(s_res_first_http_major);
1070 			break;
1071 
1072 		case s_res_first_http_major:
1073 			if (UNLIKELY(ch < '0' || ch > '9')) {
1074 				SET_ERRNO(HPE_INVALID_VERSION);
1075 				goto error;
1076 			}
1077 
1078 			parser->http_major = ch - '0';
1079 			UPDATE_STATE(s_res_http_major);
1080 			break;
1081 
1082 		/* major HTTP version or dot */
1083 		case s_res_http_major: {
1084 			if (ch == '.') {
1085 				UPDATE_STATE(s_res_first_http_minor);
1086 				break;
1087 			}
1088 
1089 			if (!IS_NUM(ch)) {
1090 				SET_ERRNO(HPE_INVALID_VERSION);
1091 				goto error;
1092 			}
1093 
1094 			parser->http_major *= 10U;
1095 			parser->http_major += ch - '0';
1096 
1097 			if (UNLIKELY(parser->http_major > 999)) {
1098 				SET_ERRNO(HPE_INVALID_VERSION);
1099 				goto error;
1100 			}
1101 
1102 			break;
1103 		}
1104 
1105 		/* first digit of minor HTTP version */
1106 		case s_res_first_http_minor:
1107 			if (UNLIKELY(!IS_NUM(ch))) {
1108 				SET_ERRNO(HPE_INVALID_VERSION);
1109 				goto error;
1110 			}
1111 
1112 			parser->http_minor = ch - '0';
1113 			UPDATE_STATE(s_res_http_minor);
1114 			break;
1115 
1116 		/* minor HTTP version or end of request line */
1117 		case s_res_http_minor: {
1118 			if (ch == ' ') {
1119 				UPDATE_STATE(s_res_first_status_code);
1120 				break;
1121 			}
1122 
1123 			if (UNLIKELY(!IS_NUM(ch))) {
1124 				SET_ERRNO(HPE_INVALID_VERSION);
1125 				goto error;
1126 			}
1127 
1128 			parser->http_minor *= 10U;
1129 			parser->http_minor += ch - '0';
1130 
1131 			if (UNLIKELY(parser->http_minor > 999)) {
1132 				SET_ERRNO(HPE_INVALID_VERSION);
1133 				goto error;
1134 			}
1135 
1136 			break;
1137 		}
1138 
1139 		case s_res_first_status_code: {
1140 			if (!IS_NUM(ch)) {
1141 				if (ch == ' ') {
1142 					break;
1143 				}
1144 
1145 				SET_ERRNO(HPE_INVALID_STATUS);
1146 				goto error;
1147 			}
1148 			parser->status_code = ch - '0';
1149 			UPDATE_STATE(s_res_status_code);
1150 			break;
1151 		}
1152 
1153 		case s_res_status_code: {
1154 			if (!IS_NUM(ch)) {
1155 				/* Numeric status only */
1156 				if ((ch == CR) || (ch == LF)) {
1157 					const char *no_status_txt = "";
1158 
1159 					rc = cb_data(parser,
1160 					     settings->on_status,
1161 					     HPE_CB_status, &p_state, parsed,
1162 					     p - data + 1, &no_status_txt, 0);
1163 					if (rc != 0) {
1164 						return rc;
1165 					}
1166 				}
1167 
1168 				switch (ch) {
1169 				case ' ':
1170 					UPDATE_STATE(s_res_status_start);
1171 					break;
1172 				case CR:
1173 					UPDATE_STATE(s_res_line_almost_done);
1174 					break;
1175 				case LF:
1176 					UPDATE_STATE(s_header_field_start);
1177 					break;
1178 				default:
1179 					SET_ERRNO(HPE_INVALID_STATUS);
1180 					goto error;
1181 				}
1182 				break;
1183 			}
1184 
1185 			parser->status_code *= 10U;
1186 			parser->status_code += ch - '0';
1187 
1188 			if (UNLIKELY(parser->status_code > 999)) {
1189 				SET_ERRNO(HPE_INVALID_STATUS);
1190 				goto error;
1191 			}
1192 
1193 			break;
1194 		}
1195 
1196 		case s_res_status_start: {
1197 			if (!status_mark && ((ch == CR) || (ch == LF))) {
1198 				/* Numeric status only */
1199 				const char *no_status_txt = "";
1200 
1201 				rc = cb_data(parser,
1202 					settings->on_status,
1203 					HPE_CB_status, &p_state, parsed,
1204 					p - data + 1, &no_status_txt, 0);
1205 				if (rc != 0) {
1206 					return rc;
1207 				}
1208 			}
1209 			if (ch == CR) {
1210 				UPDATE_STATE(s_res_line_almost_done);
1211 				break;
1212 			}
1213 
1214 			if (ch == LF) {
1215 				UPDATE_STATE(s_header_field_start);
1216 				break;
1217 			}
1218 
1219 			MARK(status);
1220 			UPDATE_STATE(s_res_status);
1221 			parser->index = 0U;
1222 			break;
1223 		}
1224 
1225 		case s_res_status:
1226 			if (ch == CR) {
1227 				UPDATE_STATE(s_res_line_almost_done);
1228 				rc = cb_data(parser, settings->on_status,
1229 					     HPE_CB_status, &p_state, parsed,
1230 					     p - data + 1, &status_mark,
1231 					     p - status_mark);
1232 				if (rc != 0) {
1233 					return rc;
1234 				}
1235 				break;
1236 			}
1237 
1238 			if (ch == LF) {
1239 				UPDATE_STATE(s_header_field_start);
1240 				rc = cb_data(parser, settings->on_status,
1241 					     HPE_CB_status, &p_state, parsed,
1242 					     p - data + 1, &status_mark,
1243 					     p - status_mark);
1244 				if (rc != 0) {
1245 					return rc;
1246 				}
1247 
1248 				break;
1249 			}
1250 
1251 			break;
1252 
1253 		case s_res_line_almost_done:
1254 			rc = strict_check(parser, ch != LF);
1255 			if (rc != 0) {
1256 				goto error;
1257 			}
1258 			UPDATE_STATE(s_header_field_start);
1259 			break;
1260 
1261 		case s_start_req: {
1262 			if (ch == CR || ch == LF) {
1263 				break;
1264 			}
1265 			parser->flags = 0U;
1266 			parser->content_length = ULLONG_MAX;
1267 			parser->content_range.start = 0U;
1268 			parser->content_range.end = 0U;
1269 			parser->content_range.total = 0U;
1270 			parser->content_range_present = false;
1271 
1272 			if (UNLIKELY(!IS_ALPHA(ch))) {
1273 				SET_ERRNO(HPE_INVALID_METHOD);
1274 				goto error;
1275 			}
1276 
1277 			parser->method = (enum http_method) 0;
1278 			parser->index = 1U;
1279 			switch (ch) {
1280 			case 'A':
1281 				parser->method = HTTP_ACL;
1282 				break;
1283 			case 'B':
1284 				parser->method = HTTP_BIND;
1285 				break;
1286 			case 'C':
1287 				parser->method = HTTP_CONNECT;
1288 				/* or COPY, CHECKOUT */
1289 				break;
1290 			case 'D':
1291 				parser->method = HTTP_DELETE;
1292 				break;
1293 			case 'G':
1294 				parser->method = HTTP_GET;
1295 				break;
1296 			case 'H':
1297 				parser->method = HTTP_HEAD;
1298 				break;
1299 			case 'L':
1300 				parser->method = HTTP_LOCK; /* or LINK */
1301 				break;
1302 			case 'M':
1303 				parser->method =
1304 					HTTP_MKCOL;
1305 				/* or MOVE, MKACTIVITY, MERGE, M-SEARCH,
1306 				 * MKCALENDAR
1307 				 */
1308 				break;
1309 			case 'N':
1310 				parser->method = HTTP_NOTIFY;
1311 				break;
1312 			case 'O':
1313 				parser->method = HTTP_OPTIONS;
1314 				break;
1315 			case 'P':
1316 				parser->method = HTTP_POST;
1317 				/* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */
1318 				break;
1319 			case 'R':
1320 				parser->method = HTTP_REPORT; /* or REBIND */
1321 				break;
1322 			case 'S':
1323 				parser->method = HTTP_SUBSCRIBE; /* or SEARCH */
1324 				break;
1325 			case 'T':
1326 				parser->method = HTTP_TRACE;
1327 				break;
1328 			case 'U':
1329 				parser->method = HTTP_UNLOCK;
1330 				/* or UNSUBSCRIBE, UNBIND, UNLINK */
1331 				break;
1332 			default:
1333 				SET_ERRNO(HPE_INVALID_METHOD);
1334 				goto error;
1335 			}
1336 			UPDATE_STATE(s_req_method);
1337 
1338 
1339 			rc = cb_notify(parser, &p_state,
1340 				       settings->on_message_begin,
1341 				       HPE_CB_message_begin, parsed,
1342 				       p - data + 1);
1343 			if (rc != 0) {
1344 				return rc;
1345 			}
1346 			break;
1347 		}
1348 
1349 		case s_req_method: {
1350 			const char *matcher;
1351 
1352 			if (UNLIKELY(ch == '\0')) {
1353 				SET_ERRNO(HPE_INVALID_METHOD);
1354 				goto error;
1355 			}
1356 
1357 			matcher = method_strings[parser->method];
1358 			if (ch == ' ' && matcher[parser->index] == '\0') {
1359 				UPDATE_STATE(s_req_spaces_before_url);
1360 			} else if (ch == matcher[parser->index]) {
1361 				; /* nada */
1362 			} else if (IS_ALPHA(ch)) {
1363 
1364 				uint64_t sw_option = parser->method << 16 |
1365 						     parser->index << 8 | ch;
1366 				switch (sw_option) {
1367 				case (HTTP_POST << 16 | 1 << 8 | 'U'):
1368 					parser->method = HTTP_PUT;
1369 					break;
1370 				case (HTTP_POST << 16 | 1 << 8 | 'A'):
1371 					parser->method = HTTP_PATCH;
1372 					break;
1373 				case (HTTP_CONNECT << 16 | 1 << 8 | 'H'):
1374 					parser->method = HTTP_CHECKOUT;
1375 					break;
1376 				case (HTTP_CONNECT << 16 | 2 << 8 | 'P'):
1377 					parser->method = HTTP_COPY;
1378 					break;
1379 				case (HTTP_MKCOL << 16 | 1 << 8 | 'O'):
1380 					parser->method = HTTP_MOVE;
1381 					break;
1382 				case (HTTP_MKCOL << 16 | 1 << 8 | 'E'):
1383 					parser->method = HTTP_MERGE;
1384 					break;
1385 				case (HTTP_MKCOL << 16 | 2 << 8 | 'A'):
1386 					parser->method = HTTP_MKACTIVITY;
1387 					break;
1388 				case (HTTP_MKCOL << 16 | 3 << 8 | 'A'):
1389 					parser->method = HTTP_MKCALENDAR;
1390 					break;
1391 				case (HTTP_SUBSCRIBE << 16 | 1 << 8 | 'E'):
1392 					parser->method = HTTP_SEARCH;
1393 					break;
1394 				case (HTTP_REPORT << 16 | 2 << 8 | 'B'):
1395 					parser->method = HTTP_REBIND;
1396 					break;
1397 				case (HTTP_POST << 16 | 1 << 8 | 'R'):
1398 					parser->method = HTTP_PROPFIND;
1399 					break;
1400 				case (HTTP_PROPFIND << 16 | 4 << 8 | 'P'):
1401 					parser->method = HTTP_PROPPATCH;
1402 					break;
1403 				case (HTTP_PUT << 16 | 2 << 8 | 'R'):
1404 					parser->method = HTTP_PURGE;
1405 					break;
1406 				case (HTTP_LOCK << 16 | 1 << 8 | 'I'):
1407 					parser->method = HTTP_LINK;
1408 					break;
1409 				case (HTTP_UNLOCK << 16 | 2 << 8 | 'S'):
1410 					parser->method = HTTP_UNSUBSCRIBE;
1411 					break;
1412 				case (HTTP_UNLOCK << 16 | 2 << 8 | 'B'):
1413 					parser->method = HTTP_UNBIND;
1414 					break;
1415 				case (HTTP_UNLOCK << 16 | 3 << 8 | 'I'):
1416 					parser->method = HTTP_UNLINK;
1417 					break;
1418 				default:
1419 					parser->http_errno = HPE_INVALID_METHOD;
1420 					goto error;
1421 				}
1422 			} else if (ch == '-' &&
1423 					parser->index == 1U &&
1424 					parser->method == HTTP_MKCOL) {
1425 				parser->method = HTTP_MSEARCH;
1426 			} else {
1427 				SET_ERRNO(HPE_INVALID_METHOD);
1428 				goto error;
1429 			}
1430 
1431 			++parser->index;
1432 			break;
1433 		}
1434 
1435 		case s_req_spaces_before_url: {
1436 			if (ch == ' ') {
1437 				break;
1438 			}
1439 
1440 			MARK(url);
1441 			if (parser->method == HTTP_CONNECT) {
1442 				UPDATE_STATE(s_req_server_start);
1443 			}
1444 
1445 			UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch));
1446 			if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1447 				SET_ERRNO(HPE_INVALID_URL);
1448 				goto error;
1449 			}
1450 
1451 			break;
1452 		}
1453 
1454 		case s_req_schema:
1455 		case s_req_schema_slash:
1456 		case s_req_schema_slash_slash:
1457 		case s_req_server_start: {
1458 			switch (ch) {
1459 			/* No whitespace allowed here */
1460 			case ' ':
1461 			case CR:
1462 			case LF:
1463 				SET_ERRNO(HPE_INVALID_URL);
1464 				goto error;
1465 			default:
1466 				UPDATE_STATE
1467 					(parse_url_char(CURRENT_STATE(), ch));
1468 				if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1469 					SET_ERRNO(HPE_INVALID_URL);
1470 					goto error;
1471 				}
1472 			}
1473 
1474 			break;
1475 		}
1476 
1477 		case s_req_server:
1478 		case s_req_server_with_at:
1479 		case s_req_path:
1480 		case s_req_query_string_start:
1481 		case s_req_query_string:
1482 		case s_req_fragment_start:
1483 		case s_req_fragment: {
1484 			switch (ch) {
1485 			case ' ':
1486 				UPDATE_STATE(s_req_http_start);
1487 				rc = cb_data(parser, settings->on_url,
1488 					     HPE_CB_url, &p_state, parsed,
1489 					     p - data + 1, &url_mark,
1490 					     p - url_mark);
1491 				if (rc != 0) {
1492 					return rc;
1493 				}
1494 
1495 				break;
1496 			case CR:
1497 			case LF:
1498 				parser->http_major = 0U;
1499 				parser->http_minor = 9U;
1500 				UPDATE_STATE((ch == CR) ?
1501 					     s_req_line_almost_done :
1502 					     s_header_field_start);
1503 				rc = cb_data(parser, settings->on_url,
1504 					     HPE_CB_url, &p_state, parsed,
1505 					     p - data + 1, &url_mark,
1506 					     p - url_mark);
1507 				if (rc != 0) {
1508 					return rc;
1509 				}
1510 
1511 				break;
1512 			default:
1513 				UPDATE_STATE
1514 					(parse_url_char(CURRENT_STATE(), ch));
1515 				if (UNLIKELY(CURRENT_STATE() == s_dead)) {
1516 					SET_ERRNO(HPE_INVALID_URL);
1517 					goto error;
1518 				}
1519 			}
1520 			break;
1521 		}
1522 
1523 		case s_req_http_start:
1524 			switch (ch) {
1525 			case 'H':
1526 				UPDATE_STATE(s_req_http_H);
1527 				break;
1528 			case ' ':
1529 				break;
1530 			default:
1531 				SET_ERRNO(HPE_INVALID_CONSTANT);
1532 				goto error;
1533 			}
1534 			break;
1535 
1536 		case s_req_http_H:
1537 			rc = strict_check(parser, ch != 'T');
1538 			if (rc != 0) {
1539 				goto error;
1540 			}
1541 			UPDATE_STATE(s_req_http_HT);
1542 			break;
1543 
1544 		case s_req_http_HT:
1545 			rc = strict_check(parser, ch != 'T');
1546 			if (rc != 0) {
1547 				goto error;
1548 			}
1549 			UPDATE_STATE(s_req_http_HTT);
1550 			break;
1551 
1552 		case s_req_http_HTT:
1553 			rc = strict_check(parser, ch != 'P');
1554 			if (rc != 0) {
1555 				goto error;
1556 			}
1557 			UPDATE_STATE(s_req_http_HTTP);
1558 			break;
1559 
1560 		case s_req_http_HTTP:
1561 			rc = strict_check(parser, ch != '/');
1562 			if (rc != 0) {
1563 				goto error;
1564 			}
1565 			UPDATE_STATE(s_req_first_http_major);
1566 			break;
1567 
1568 		/* first digit of major HTTP version */
1569 		case s_req_first_http_major:
1570 			if (UNLIKELY(ch < '1' || ch > '9')) {
1571 				SET_ERRNO(HPE_INVALID_VERSION);
1572 				goto error;
1573 			}
1574 
1575 			parser->http_major = ch - '0';
1576 			UPDATE_STATE(s_req_http_major);
1577 			break;
1578 
1579 		/* major HTTP version or dot */
1580 		case s_req_http_major: {
1581 			if (ch == '.') {
1582 				UPDATE_STATE(s_req_first_http_minor);
1583 				break;
1584 			}
1585 
1586 			if (UNLIKELY(!IS_NUM(ch))) {
1587 				SET_ERRNO(HPE_INVALID_VERSION);
1588 				goto error;
1589 			}
1590 
1591 			parser->http_major *= 10U;
1592 			parser->http_major += ch - '0';
1593 
1594 			if (UNLIKELY(parser->http_major > 999)) {
1595 				SET_ERRNO(HPE_INVALID_VERSION);
1596 				goto error;
1597 			}
1598 
1599 			break;
1600 		}
1601 
1602 		/* first digit of minor HTTP version */
1603 		case s_req_first_http_minor:
1604 			if (UNLIKELY(!IS_NUM(ch))) {
1605 				SET_ERRNO(HPE_INVALID_VERSION);
1606 				goto error;
1607 			}
1608 
1609 			parser->http_minor = ch - '0';
1610 			UPDATE_STATE(s_req_http_minor);
1611 			break;
1612 
1613 		/* minor HTTP version or end of request line */
1614 		case s_req_http_minor: {
1615 			if (ch == CR) {
1616 				UPDATE_STATE(s_req_line_almost_done);
1617 				break;
1618 			}
1619 
1620 			if (ch == LF) {
1621 				UPDATE_STATE(s_header_field_start);
1622 				break;
1623 			}
1624 
1625 			/* XXX allow spaces after digit? */
1626 
1627 			if (UNLIKELY(!IS_NUM(ch))) {
1628 				SET_ERRNO(HPE_INVALID_VERSION);
1629 				goto error;
1630 			}
1631 
1632 			parser->http_minor *= 10U;
1633 			parser->http_minor += ch - '0';
1634 
1635 			if (UNLIKELY(parser->http_minor > 999)) {
1636 				SET_ERRNO(HPE_INVALID_VERSION);
1637 				goto error;
1638 			}
1639 
1640 			break;
1641 		}
1642 
1643 		/* end of request line */
1644 		case s_req_line_almost_done: {
1645 			if (UNLIKELY(ch != LF)) {
1646 				SET_ERRNO(HPE_LF_EXPECTED);
1647 				goto error;
1648 			}
1649 
1650 			UPDATE_STATE(s_header_field_start);
1651 			break;
1652 		}
1653 
1654 		case s_header_field_start: {
1655 			if (ch == CR) {
1656 				UPDATE_STATE(s_headers_almost_done);
1657 				break;
1658 			}
1659 
1660 			if (ch == LF) {
1661 				/* they might be just sending \n instead of \r\n
1662 				 * so this would be
1663 				 * the second \n to denote the end of headers
1664 				 */
1665 				UPDATE_STATE(s_headers_almost_done);
1666 				goto reexecute;
1667 			}
1668 
1669 			c = TOKEN(ch);
1670 
1671 			if (UNLIKELY(!c)) {
1672 				SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1673 				goto error;
1674 			}
1675 
1676 			MARK(header_field);
1677 
1678 			parser->index = 0U;
1679 			UPDATE_STATE(s_header_field);
1680 
1681 			switch (c) {
1682 			case 'c':
1683 				parser->header_state = h_C;
1684 				break;
1685 
1686 			case 'p':
1687 				parser->header_state =
1688 					h_matching_proxy_connection;
1689 				break;
1690 
1691 			case 't':
1692 				parser->header_state =
1693 					h_matching_transfer_encoding;
1694 				break;
1695 
1696 			case 'u':
1697 				parser->header_state = h_matching_upgrade;
1698 				break;
1699 
1700 			default:
1701 				parser->header_state = h_general;
1702 				break;
1703 			}
1704 			break;
1705 		}
1706 
1707 		case s_header_field: {
1708 			const char *start = p;
1709 
1710 			for (; p != data + len; p++) {
1711 				ch = *p;
1712 				c = TOKEN(ch);
1713 
1714 				if (!c) {
1715 					break;
1716 				}
1717 				parser_header_state(parser, ch, c);
1718 			}
1719 
1720 			rc = count_header_size(parser, p - start);
1721 			if (rc != 0) {
1722 				goto error;
1723 			}
1724 
1725 			if (p == data + len) {
1726 				--p;
1727 				break;
1728 			}
1729 
1730 			if (ch == ':') {
1731 				UPDATE_STATE(s_header_value_discard_ws);
1732 				rc = cb_data(parser, settings->on_header_field,
1733 					     HPE_CB_header_field, &p_state,
1734 					     parsed, p - data + 1,
1735 					     &header_field_mark,
1736 					     p - header_field_mark);
1737 				if (rc != 0) {
1738 					return rc;
1739 				}
1740 
1741 				break;
1742 			}
1743 
1744 			SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1745 			goto error;
1746 		}
1747 
1748 		case s_header_value_discard_ws:
1749 			if (ch == ' ' || ch == '\t') {
1750 				break;
1751 			}
1752 
1753 			if (ch == CR) {
1754 				UPDATE_STATE
1755 					(s_header_value_discard_ws_almost_done);
1756 				break;
1757 			}
1758 
1759 			if (ch == LF) {
1760 				UPDATE_STATE(s_header_value_discard_lws);
1761 				break;
1762 			}
1763 
1764 			__fallthrough;
1765 
1766 		case s_header_value_start: {
1767 			MARK(header_value);
1768 
1769 			UPDATE_STATE(s_header_value);
1770 			parser->index = 0U;
1771 
1772 			c = LOWER(ch);
1773 
1774 			switch (parser->header_state) {
1775 			case h_upgrade:
1776 				parser->flags |= F_UPGRADE;
1777 				parser->header_state = h_general;
1778 				break;
1779 
1780 			case h_transfer_encoding:
1781 				/* looking for 'Transfer-Encoding: chunked' */
1782 				if ('c' == c) {
1783 					parser->header_state =
1784 					   h_matching_transfer_encoding_chunked;
1785 				} else {
1786 					parser->header_state = h_general;
1787 				}
1788 				break;
1789 
1790 			case h_content_length:
1791 				if (UNLIKELY(!IS_NUM(ch))) {
1792 					SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
1793 					goto error;
1794 				}
1795 
1796 				if (parser->flags & F_CONTENTLENGTH) {
1797 					SET_ERRNO
1798 						(HPE_UNEXPECTED_CONTENT_LENGTH);
1799 					goto error;
1800 				}
1801 
1802 				parser->flags |= F_CONTENTLENGTH;
1803 				parser->content_length = ch - '0';
1804 				break;
1805 
1806 			case h_content_range_start:
1807 				if (parser->content_range_present) {
1808 					SET_ERRNO(HPE_UNEXPECTED_CONTENT_RANGE);
1809 					goto error;
1810 				}
1811 
1812 				parser->content_range_present = true;
1813 				parser->content_range.start = 0;
1814 				break;
1815 
1816 			case h_connection:
1817 				/* looking for 'Connection: keep-alive' */
1818 				if (c == 'k') {
1819 					parser->header_state =
1820 					h_matching_connection_keep_alive;
1821 					/* looking for 'Connection: close' */
1822 				} else if (c == 'c') {
1823 					parser->header_state =
1824 						h_matching_connection_close;
1825 				} else if (c == 'u') {
1826 					parser->header_state =
1827 						h_matching_connection_upgrade;
1828 				} else {
1829 					parser->header_state =
1830 						h_matching_connection_token;
1831 				}
1832 				break;
1833 
1834 			/* Multi-value `Connection` header */
1835 			case h_matching_connection_token_start:
1836 				break;
1837 
1838 			default:
1839 				parser->header_state = h_general;
1840 				break;
1841 			}
1842 			break;
1843 		}
1844 
1845 		case s_header_value: {
1846 			const char *start = p;
1847 			enum header_states h_state =
1848 				(enum header_states)parser->header_state;
1849 
1850 			for (; p != data + len; p++) {
1851 				ch = *p;
1852 				if (ch == CR) {
1853 					UPDATE_STATE(s_header_almost_done);
1854 					parser->header_state = h_state;
1855 					rc = cb_data(parser,
1856 						     settings->on_header_value,
1857 						     HPE_CB_header_value,
1858 						     &p_state, parsed,
1859 						     p - data + 1,
1860 						     &header_value_mark,
1861 						     p - header_value_mark);
1862 					if (rc != 0) {
1863 						return rc;
1864 					}
1865 
1866 					break;
1867 				}
1868 
1869 				if (ch == LF) {
1870 					UPDATE_STATE(s_header_almost_done);
1871 					rc = count_header_size(parser,
1872 							       p - start);
1873 					if (rc != 0) {
1874 						goto error;
1875 					}
1876 					parser->header_state = h_state;
1877 					rc = cb_data(parser,
1878 						     settings->on_header_value,
1879 						     HPE_CB_header_value,
1880 						     &p_state, parsed, p - data,
1881 						     &header_value_mark,
1882 						     p - header_value_mark);
1883 					if (rc != 0) {
1884 						return rc;
1885 					}
1886 
1887 					goto reexecute;
1888 				}
1889 
1890 				if (!lenient && !IS_HEADER_CHAR(ch)) {
1891 					SET_ERRNO(HPE_INVALID_HEADER_TOKEN);
1892 					goto error;
1893 				}
1894 
1895 				c = LOWER(ch);
1896 
1897 				rc = header_states(parser, data, len, &p,
1898 						   &p_state, &h_state, ch, c);
1899 				if (rc != 0) {
1900 					goto error;
1901 				}
1902 
1903 			}
1904 			parser->header_state = h_state;
1905 
1906 			rc = count_header_size(parser, p - start);
1907 			if (rc != 0) {
1908 				goto error;
1909 			}
1910 
1911 			if (p == data + len) {
1912 				--p;
1913 			}
1914 			break;
1915 		}
1916 
1917 		case s_header_almost_done: {
1918 			if (UNLIKELY(ch != LF)) {
1919 				SET_ERRNO(HPE_LF_EXPECTED);
1920 				goto error;
1921 			}
1922 
1923 			UPDATE_STATE(s_header_value_lws);
1924 			break;
1925 		}
1926 
1927 		case s_header_value_lws: {
1928 			if (ch == ' ' || ch == '\t') {
1929 				UPDATE_STATE(s_header_value_start);
1930 				goto reexecute;
1931 			}
1932 
1933 			/* finished the header */
1934 			switch (parser->header_state) {
1935 			case h_connection_keep_alive:
1936 				parser->flags |= F_CONNECTION_KEEP_ALIVE;
1937 				break;
1938 			case h_connection_close:
1939 				parser->flags |= F_CONNECTION_CLOSE;
1940 				break;
1941 			case h_transfer_encoding_chunked:
1942 				parser->flags |= F_CHUNKED;
1943 				break;
1944 			case h_connection_upgrade:
1945 				parser->flags |= F_CONNECTION_UPGRADE;
1946 				break;
1947 			default:
1948 				break;
1949 			}
1950 
1951 			UPDATE_STATE(s_header_field_start);
1952 			goto reexecute;
1953 		}
1954 
1955 		case s_header_value_discard_ws_almost_done: {
1956 			rc = strict_check(parser, ch != LF);
1957 			if (rc != 0) {
1958 				goto error;
1959 			}
1960 			UPDATE_STATE(s_header_value_discard_lws);
1961 			break;
1962 		}
1963 
1964 		case s_header_value_discard_lws: {
1965 			if (ch == ' ' || ch == '\t') {
1966 				UPDATE_STATE(s_header_value_discard_ws);
1967 				break;
1968 			}
1969 			switch (parser->header_state) {
1970 			case h_connection_keep_alive:
1971 				parser->flags |=
1972 					F_CONNECTION_KEEP_ALIVE;
1973 				break;
1974 			case h_connection_close:
1975 				parser->flags |= F_CONNECTION_CLOSE;
1976 				break;
1977 			case h_connection_upgrade:
1978 				parser->flags |= F_CONNECTION_UPGRADE;
1979 				break;
1980 			case h_transfer_encoding_chunked:
1981 				parser->flags |= F_CHUNKED;
1982 				break;
1983 			default:
1984 				break;
1985 			}
1986 
1987 			/* header value was empty */
1988 			MARK(header_value);
1989 			UPDATE_STATE(s_header_field_start);
1990 			rc = cb_data(parser, settings->on_header_value,
1991 				     HPE_CB_header_value, &p_state, parsed,
1992 				     p - data, &header_value_mark,
1993 				     p - header_value_mark);
1994 			if (rc != 0) {
1995 				return rc;
1996 			}
1997 
1998 			goto reexecute;
1999 		}
2000 
2001 		case s_headers_almost_done: {
2002 			rc = strict_check(parser, ch != LF);
2003 			if (rc != 0) {
2004 				goto error;
2005 			}
2006 
2007 			if (parser->flags & F_TRAILING) {
2008 				/* End of a chunked request */
2009 				UPDATE_STATE(s_message_done);
2010 
2011 				rc = cb_notify(parser, &p_state,
2012 					       settings->on_chunk_complete,
2013 					       HPE_CB_chunk_complete, parsed,
2014 					       p - data);
2015 				if (rc != 0) {
2016 					return rc;
2017 				}
2018 				goto reexecute;
2019 			}
2020 
2021 			/* Cannot use chunked encoding and a content-length
2022 			 * header together per the HTTP specification.
2023 			 */
2024 			if ((parser->flags & F_CHUNKED) &&
2025 					(parser->flags & F_CONTENTLENGTH)) {
2026 				SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH);
2027 				goto error;
2028 			}
2029 
2030 			UPDATE_STATE(s_headers_done);
2031 
2032 			/* Set this here so that on_headers_complete() callbacks
2033 			 * can see it
2034 			 */
2035 			int flags = (F_UPGRADE | F_CONNECTION_UPGRADE);
2036 
2037 			parser->upgrade =
2038 				((parser->flags & flags) == flags ||
2039 				 parser->method == HTTP_CONNECT);
2040 
2041 			/* Here we call the headers_complete callback. This is
2042 			 * somewhat
2043 			 * different than other callbacks because if the user
2044 			 * returns 1, we
2045 			 * will interpret that as saying that this message has
2046 			 * no body. This
2047 			 * is needed for the annoying case of receiving a
2048 			 * response to a HEAD
2049 			 * request.
2050 			 *
2051 			 * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but
2052 			 * we cannot, so
2053 			 * we have to simulate it by handling a change in errno
2054 			 * below.
2055 			 */
2056 			if (settings->on_headers_complete) {
2057 				switch (settings->on_headers_complete(parser)) {
2058 				case 0:
2059 					break;
2060 
2061 				case 2:
2062 					parser->upgrade = 1U;
2063 					__fallthrough;
2064 
2065 				case 1:
2066 					parser->flags |= F_SKIPBODY;
2067 					break;
2068 
2069 				default:
2070 					SET_ERRNO(HPE_CB_headers_complete);
2071 
2072 					parser->state = CURRENT_STATE();
2073 					*parsed = p - data;
2074 					return -HTTP_PARSER_ERRNO(parser);
2075 				}
2076 			}
2077 
2078 			if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {
2079 				parser->state = CURRENT_STATE();
2080 				*parsed = p - data;
2081 				return -HTTP_PARSER_ERRNO(parser);
2082 			}
2083 
2084 			goto reexecute;
2085 		}
2086 
2087 		case s_headers_done: {
2088 			int hasBody;
2089 
2090 			rc = strict_check(parser, ch != LF);
2091 			if (rc != 0) {
2092 				goto error;
2093 			}
2094 
2095 			parser->nread = 0U;
2096 
2097 			hasBody = parser->flags & F_CHUNKED ||
2098 				  (parser->content_length > 0 &&
2099 				   parser->content_length != ULLONG_MAX);
2100 			if (parser->upgrade &&
2101 				(parser->method == HTTP_CONNECT ||
2102 				 (parser->flags & F_SKIPBODY) || !hasBody)) {
2103 				/* Exit, the rest of the message is in a
2104 				 * different protocol.
2105 				 */
2106 				UPDATE_STATE(NEW_MESSAGE());
2107 
2108 				rc = cb_notify(parser, &p_state,
2109 					       settings->on_message_complete,
2110 					       HPE_CB_message_complete, parsed,
2111 					       p - data + 1);
2112 				if (rc != 0) {
2113 					return rc;
2114 				}
2115 				parser->state = CURRENT_STATE();
2116 				*parsed = p - data + 1;
2117 				return 0;
2118 			}
2119 
2120 			if (parser->flags & F_SKIPBODY) {
2121 				UPDATE_STATE(NEW_MESSAGE());
2122 
2123 				rc = cb_notify(parser, &p_state,
2124 					       settings->on_message_complete,
2125 					       HPE_CB_message_complete, parsed,
2126 					       p - data + 1);
2127 				if (rc != 0) {
2128 					return rc;
2129 				}
2130 
2131 			} else if (parser->flags & F_CHUNKED) {
2132 				/* chunked encoding - ignore Content-Length
2133 				 * header
2134 				 */
2135 				UPDATE_STATE(s_chunk_size_start);
2136 			} else {
2137 				rc = zero_content_length(parser, settings,
2138 							 &p_state, parsed, p,
2139 							 data);
2140 				if (rc != 0) {
2141 					return rc;
2142 				}
2143 			}
2144 
2145 			break;
2146 		}
2147 
2148 		case s_body_identity: {
2149 			uint64_t to_read = MIN(parser->content_length,
2150 					       (uint64_t) ((data + len) - p));
2151 
2152 			__ASSERT_NO_MSG(parser->content_length != 0U
2153 			       && parser->content_length != ULLONG_MAX);
2154 
2155 			/* The difference between advancing content_length and
2156 			 * p is because
2157 			 * the latter will automatically advance on the next
2158 			 * loop
2159 			 * iteration.
2160 			 * Further, if content_length ends up at 0, we want to
2161 			 * see the last
2162 			 * byte again for our message complete callback.
2163 			 */
2164 			MARK(body);
2165 			parser->content_length -= to_read;
2166 			p += to_read - 1;
2167 
2168 			if (parser->content_length == 0U) {
2169 				UPDATE_STATE(s_message_done);
2170 
2171 				/* Mimic CALLBACK_DATA_NOADVANCE() but with one
2172 				 * extra byte.
2173 				 *
2174 				 * The alternative to doing this is to wait for
2175 				 * the next byte to
2176 				 * trigger the data callback, just as in every
2177 				 * other case. The
2178 				 * problem with this is that this makes it
2179 				 * difficult for the test
2180 				 * harness to distinguish between
2181 				 * complete-on-EOF and
2182 				 * complete-on-length. It's not clear that this
2183 				 * distinction is
2184 				 * important for applications, but let's keep it
2185 				 * for now.
2186 				 */
2187 
2188 				rc = cb_data(parser, settings->on_body,
2189 					     HPE_CB_body, &p_state, parsed,
2190 					     p - data, &body_mark,
2191 					     p - body_mark + 1);
2192 				if (rc != 0) {
2193 					return rc;
2194 				}
2195 
2196 				goto reexecute;
2197 			}
2198 
2199 			break;
2200 		}
2201 
2202 		/* read until EOF */
2203 		case s_body_identity_eof:
2204 			MARK(body);
2205 			p = data + len - 1;
2206 
2207 			break;
2208 
2209 		case s_message_done:
2210 			UPDATE_STATE(NEW_MESSAGE());
2211 
2212 			rc = cb_notify(parser, &p_state,
2213 				       settings->on_message_complete,
2214 				       HPE_CB_message_complete, parsed,
2215 				       p - data + 1);
2216 			if (rc != 0) {
2217 				return rc;
2218 			}
2219 			if (parser->upgrade) {
2220 				/* Exit, the rest of the message is in a
2221 				 * different protocol.
2222 				 */
2223 				parser->state = CURRENT_STATE();
2224 				*parsed = p - data + 1;
2225 				return 0;
2226 			}
2227 			break;
2228 
2229 		case s_chunk_size_start: {
2230 			__ASSERT_NO_MSG(parser->nread == 1U);
2231 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2232 
2233 			unhex_val = unhex[(unsigned char)ch];
2234 			if (UNLIKELY(unhex_val == -1)) {
2235 				SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
2236 				goto error;
2237 			}
2238 
2239 			parser->content_length = unhex_val;
2240 			UPDATE_STATE(s_chunk_size);
2241 			break;
2242 		}
2243 
2244 		case s_chunk_size: {
2245 			uint64_t t;
2246 
2247 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2248 
2249 			if (ch == CR) {
2250 				UPDATE_STATE(s_chunk_size_almost_done);
2251 				break;
2252 			}
2253 
2254 			unhex_val = unhex[(unsigned char)ch];
2255 
2256 			if (unhex_val == -1) {
2257 				if (ch == ';' || ch == ' ') {
2258 					UPDATE_STATE(s_chunk_parameters);
2259 					break;
2260 				}
2261 
2262 				SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
2263 				goto error;
2264 			}
2265 
2266 			t = parser->content_length;
2267 			t *= 16U;
2268 			t += unhex_val;
2269 
2270 			/* Overflow? Test against a conservative limit for
2271 			 * simplicity.
2272 			 */
2273 			uint64_t ulong_value = (ULLONG_MAX - 16) / 16;
2274 
2275 			if (UNLIKELY(ulong_value < parser->content_length)) {
2276 				SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);
2277 				goto error;
2278 			}
2279 
2280 			parser->content_length = t;
2281 			break;
2282 		}
2283 
2284 		case s_chunk_parameters: {
2285 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2286 			/* just ignore this shit. TODO check for overflow */
2287 			if (ch == CR) {
2288 				UPDATE_STATE(s_chunk_size_almost_done);
2289 				break;
2290 			}
2291 			break;
2292 		}
2293 
2294 		case s_chunk_size_almost_done: {
2295 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2296 
2297 			rc = strict_check(parser, ch != LF);
2298 			if (rc != 0) {
2299 				goto error;
2300 			}
2301 
2302 			parser->nread = 0U;
2303 
2304 			if (parser->content_length == 0U) {
2305 				parser->flags |= F_TRAILING;
2306 				UPDATE_STATE(s_header_field_start);
2307 			} else {
2308 				UPDATE_STATE(s_chunk_data);
2309 			}
2310 
2311 			rc = cb_notify(parser, &p_state,
2312 				       settings->on_chunk_header,
2313 				       HPE_CB_chunk_header, parsed,
2314 				       p - data + 1);
2315 			if (rc != 0) {
2316 				return rc;
2317 			}
2318 			break;
2319 		}
2320 
2321 		case s_chunk_data: {
2322 			uint64_t to_read = MIN(parser->content_length,
2323 					       (uint64_t) ((data + len) - p));
2324 
2325 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2326 			__ASSERT_NO_MSG(parser->content_length != 0U
2327 					&& parser->content_length != ULLONG_MAX);
2328 
2329 			/* See the explanation in s_body_identity for why the
2330 			 * content
2331 			 * length and data pointers are managed this way.
2332 			 */
2333 			MARK(body);
2334 			parser->content_length -= to_read;
2335 			p += to_read - 1;
2336 
2337 			if (parser->content_length == 0U) {
2338 				UPDATE_STATE(s_chunk_data_almost_done);
2339 			}
2340 
2341 			break;
2342 		}
2343 
2344 		case s_chunk_data_almost_done:
2345 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2346 			__ASSERT_NO_MSG(parser->content_length == 0U);
2347 			rc = strict_check(parser, ch != CR);
2348 			if (rc != 0) {
2349 				goto error;
2350 			}
2351 			UPDATE_STATE(s_chunk_data_done);
2352 			rc = cb_data(parser, settings->on_body, HPE_CB_body,
2353 				     &p_state, parsed, p - data + 1, &body_mark,
2354 				     p - body_mark);
2355 			if (rc != 0) {
2356 				return rc;
2357 			}
2358 
2359 			break;
2360 
2361 		case s_chunk_data_done:
2362 			__ASSERT_NO_MSG(parser->flags & F_CHUNKED);
2363 			rc = strict_check(parser, ch != LF);
2364 			if (rc != 0) {
2365 				goto error;
2366 			}
2367 			parser->nread = 0U;
2368 			UPDATE_STATE(s_chunk_size_start);
2369 
2370 			rc = cb_notify(parser, &p_state,
2371 				       settings->on_chunk_complete,
2372 				       HPE_CB_chunk_complete, parsed,
2373 				       p - data + 1);
2374 			if (rc != 0) {
2375 				return rc;
2376 			}
2377 			break;
2378 
2379 		default:
2380 			__ASSERT_NO_MSG(0 && "unhandled state");
2381 			SET_ERRNO(HPE_INVALID_INTERNAL_STATE);
2382 			goto error;
2383 		}
2384 	}
2385 
2386 	/* Run callbacks for any marks that we have leftover after we ran our of
2387 	 * bytes. There should be at most one of these set, so it's OK to invoke
2388 	 * them in series (unset marks will not result in callbacks).
2389 	 *
2390 	 * We use the NOADVANCE() variety of callbacks here because 'p' has
2391 	 * already
2392 	 * overflowed 'data' and this allows us to correct for the off-by-one
2393 	 * that
2394 	 * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a
2395 	 * 'p'
2396 	 * value that's in-bounds).
2397 	 */
2398 
2399 	__ASSERT_NO_MSG(((header_field_mark ? 1 : 0) +
2400 			(header_value_mark ? 1 : 0) +
2401 			(url_mark ? 1 : 0)  +
2402 			(body_mark ? 1 : 0) +
2403 			(status_mark ? 1 : 0)) <= 1);
2404 
2405 	rc = cb_data(parser, settings->on_header_field, HPE_CB_header_field,
2406 		     &p_state, parsed, p - data, &header_field_mark,
2407 		     p - header_field_mark);
2408 	if (rc != 0) {
2409 		return rc;
2410 	}
2411 	rc = cb_data(parser, settings->on_header_value, HPE_CB_header_value,
2412 		     &p_state, parsed, p - data, &header_value_mark,
2413 		     p - header_value_mark);
2414 	if (rc != 0) {
2415 		return rc;
2416 	}
2417 	rc = cb_data(parser, settings->on_url, HPE_CB_url, &p_state, parsed,
2418 		     p - data, &url_mark, p - url_mark);
2419 	if (rc != 0) {
2420 		return rc;
2421 	}
2422 	rc = cb_data(parser, settings->on_body, HPE_CB_body, &p_state, parsed,
2423 		     p - data, &body_mark, p - body_mark);
2424 	if (rc != 0) {
2425 		return rc;
2426 	}
2427 	rc = cb_data(parser, settings->on_status, HPE_CB_status, &p_state,
2428 		     parsed, p - data, &status_mark, p - status_mark);
2429 	if (rc != 0) {
2430 		return rc;
2431 	}
2432 
2433 	parser->state = CURRENT_STATE();
2434 	*parsed = len;
2435 	return 0;
2436 
2437 error:
2438 	if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {
2439 		SET_ERRNO(HPE_UNKNOWN);
2440 	}
2441 
2442 	parser->state = CURRENT_STATE();
2443 	*parsed = p - data; /* Error */
2444 	return -HTTP_PARSER_ERRNO(parser);
2445 }
2446 
http_parser_execute(struct http_parser * parser,const struct http_parser_settings * settings,const char * data,size_t len)2447 size_t http_parser_execute(struct http_parser *parser,
2448 			   const struct http_parser_settings *settings,
2449 			   const char *data, size_t len)
2450 {
2451 	size_t parsed;
2452 
2453 	parser_execute(parser, settings, data, len, &parsed);
2454 	return parsed;
2455 }
2456 
2457 /* Does the parser need to see an EOF to find the end of the message? */
http_message_needs_eof(const struct http_parser * parser)2458 int http_message_needs_eof(const struct http_parser *parser)
2459 {
2460 	if (parser->type == HTTP_REQUEST) {
2461 		return 0;
2462 	}
2463 
2464 	/* See RFC 2616 section 4.4 */
2465 	if (parser->status_code / 100 == 1U || /* 1xx e.g. Continue */
2466 			parser->status_code == 204U ||     /* No Content */
2467 			parser->status_code == 304U ||     /* Not Modified */
2468 			parser->flags & F_SKIPBODY) {     /* response to a HEAD
2469 							   * request
2470 							   */
2471 		return 0;
2472 	}
2473 
2474 	if ((parser->flags & F_CHUNKED) ||
2475 			parser->content_length != ULLONG_MAX) {
2476 		return 0;
2477 	}
2478 
2479 	return 1;
2480 }
2481 
2482 
http_should_keep_alive(const struct http_parser * parser)2483 int http_should_keep_alive(const struct http_parser *parser)
2484 {
2485 	if (parser->http_major > 0 && parser->http_minor > 0) {
2486 		/* HTTP/1.1 */
2487 		if (parser->flags & F_CONNECTION_CLOSE) {
2488 			return 0;
2489 		}
2490 	} else {
2491 		/* HTTP/1.0 or earlier */
2492 		if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
2493 			return 0;
2494 		}
2495 	}
2496 
2497 	return !http_message_needs_eof(parser);
2498 }
2499 
2500 
http_method_str(enum http_method m)2501 const char *http_method_str(enum http_method m)
2502 {
2503 	return ELEM_AT(method_strings, m, "<unknown>");
2504 }
2505 
2506 
http_parser_init(struct http_parser * parser,enum http_parser_type t)2507 void http_parser_init(struct http_parser *parser, enum http_parser_type t)
2508 {
2509 	void *data = parser->data; /* preserve application data */
2510 
2511 	(void)memset(parser, 0, sizeof(*parser));
2512 	parser->data = data;
2513 	parser->type = t;
2514 	parser->state =
2515 		(t == HTTP_REQUEST ? s_start_req :
2516 		 (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));
2517 	parser->http_errno = HPE_OK;
2518 }
2519 
http_parser_settings_init(struct http_parser_settings * settings)2520 void http_parser_settings_init(struct http_parser_settings *settings)
2521 {
2522 	(void)memset(settings, 0, sizeof(*settings));
2523 }
2524 
http_errno_name(enum http_errno err)2525 const char *http_errno_name(enum http_errno err)
2526 {
2527 	__ASSERT_NO_MSG(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2528 
2529 	return http_strerror_tab[err].name;
2530 }
2531 
http_errno_description(enum http_errno err)2532 const char *http_errno_description(enum http_errno err)
2533 {
2534 	__ASSERT_NO_MSG(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
2535 
2536 	return http_strerror_tab[err].description;
2537 }
2538 
http_parser_pause(struct http_parser * parser,int paused)2539 void http_parser_pause(struct http_parser *parser, int paused)
2540 {
2541 	/* Users should only be pausing/unpausing a parser that is not in an
2542 	 * error
2543 	 * state. In non-debug builds, there's not much that we can do about
2544 	 * this
2545 	 * other than ignore it.
2546 	 */
2547 	if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||
2548 			HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {
2549 		SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);
2550 	} else {
2551 		__ASSERT_NO_MSG(0 && "Attempting to pause parser in error state");
2552 	}
2553 }
2554 
http_body_is_final(const struct http_parser * parser)2555 int http_body_is_final(const struct http_parser *parser)
2556 {
2557 	return parser->state == s_message_done;
2558 }
2559 
http_parser_version(void)2560 unsigned long http_parser_version(void)
2561 {
2562 	return HTTP_PARSER_VERSION_MAJOR * 0x10000 |
2563 	       HTTP_PARSER_VERSION_MINOR * 0x00100 |
2564 	       HTTP_PARSER_VERSION_PATCH * 0x00001;
2565 }
2566