3232#endif
3333
3434
35- #define MAX_FIELD_SIZE (80*1024)
36-
37-
3835#define CALLBACK2 (FOR ) \
3936do { \
4037 if (settings->on_##FOR) { \
@@ -45,20 +42,16 @@ do { \
4542
4643#define MARK (FOR ) \
4744do { \
48- parser->FOR##_mark = p; \
49- parser->FOR##_size = 0; \
45+ FOR##_mark = p; \
5046} while (0)
5147
52-
5348#define CALLBACK_NOCLEAR (FOR ) \
5449do { \
55- if (parser->FOR##_mark) { \
56- parser->FOR##_size += p - parser->FOR##_mark; \
57- if (parser->FOR##_size > MAX_FIELD_SIZE) return (p - data); \
50+ if (FOR##_mark) { \
5851 if (settings->on_##FOR) { \
5952 if (0 != settings->on_##FOR(parser, \
60- parser-> FOR##_mark, \
61- p - parser-> FOR##_mark)) \
53+ FOR##_mark, \
54+ p - FOR##_mark)) \
6255 { \
6356 return (p - data); \
6457 } \
7063#define CALLBACK (FOR ) \
7164do { \
7265 CALLBACK_NOCLEAR(FOR); \
73- parser-> FOR##_mark = NULL; \
66+ FOR##_mark = NULL; \
7467} while (0)
7568
7669
@@ -132,6 +125,8 @@ static const uint32_t usual[] = {
132125enum state
133126 { s_dead = 1 /* important that this is > 0 */
134127
128+ , s_start_res_or_resp
129+ , s_res_or_resp_H
135130 , s_start_res
136131 , s_res_H
137132 , s_res_HT
@@ -303,12 +298,31 @@ size_t http_parser_execute (http_parser *parser,
303298 return 0 ;
304299 }
305300
306- if (parser -> header_field_mark ) parser -> header_field_mark = data ;
307- if (parser -> header_value_mark ) parser -> header_value_mark = data ;
308- if (parser -> fragment_mark ) parser -> fragment_mark = data ;
309- if (parser -> query_string_mark ) parser -> query_string_mark = data ;
310- if (parser -> path_mark ) parser -> path_mark = data ;
311- if (parser -> url_mark ) parser -> url_mark = data ;
301+ /* technically we could combine all of these (except for url_mark) into one
302+ variable, saving stack space, but it seems more clear to have them
303+ separated. */
304+ const char * header_field_mark = 0 ;
305+ const char * header_value_mark = 0 ;
306+ const char * fragment_mark = 0 ;
307+ const char * query_string_mark = 0 ;
308+ const char * path_mark = 0 ;
309+ const char * url_mark = 0 ;
310+
311+ if (state == s_header_field )
312+ header_field_mark = data ;
313+ if (state == s_header_value )
314+ header_value_mark = data ;
315+ if (state == s_req_fragment )
316+ fragment_mark = data ;
317+ if (state == s_req_query_string )
318+ query_string_mark = data ;
319+ if (state == s_req_path )
320+ path_mark = data ;
321+ if (state == s_req_path || state == s_req_schema || state == s_req_schema_slash
322+ || state == s_req_schema_slash_slash || state == s_req_port
323+ || state == s_req_query_string_start || state == s_req_query_string
324+ || state == s_req_fragment_start || state == s_req_fragment )
325+ url_mark = data ;
312326
313327 for (p = data , pe = data + len ; p != pe ; p ++ ) {
314328 ch = * p ;
@@ -326,6 +340,42 @@ size_t http_parser_execute (http_parser *parser,
326340 */
327341 goto error ;
328342
343+ case s_start_res_or_resp :
344+ {
345+ if (ch == CR || ch == LF )
346+ break ;
347+ parser -> flags = 0 ;
348+ parser -> content_length = -1 ;
349+
350+ CALLBACK2 (message_begin );
351+
352+ if (ch == 'H' )
353+ state = s_res_or_resp_H ;
354+ else {
355+ parser -> type = HTTP_REQUEST ;
356+ if (ch < 'A' || 'Z' < ch ) goto error ;
357+ parser -> buffer [0 ] = ch ;
358+ index = 0 ;
359+ state = s_req_method ;
360+ }
361+ break ;
362+ }
363+
364+ case s_res_or_resp_H :
365+ if (ch == 'T' ) {
366+ parser -> type = HTTP_RESPONSE ;
367+ state = s_res_HT ;
368+ } else {
369+ if (ch < 'A' || 'Z' < ch ) goto error ;
370+ parser -> type = HTTP_REQUEST ;
371+ parser -> method = (enum http_method ) 0 ;
372+ parser -> buffer [0 ] = 'H' ;
373+ parser -> buffer [1 ] = ch ;
374+ index = 1 ;
375+ state = s_req_method ;
376+ }
377+ break ;
378+
329379 case s_start_res :
330380 {
331381 parser -> flags = 0 ;
@@ -584,7 +634,7 @@ size_t http_parser_execute (http_parser *parser,
584634 break ;
585635
586636 case 9 :
587- if (ngx_str9cmp (parser -> buffer ,
637+ if (ngx_str9cmp (parser -> buffer ,
588638 'P' , 'R' , 'O' , 'P' , 'P' , 'A' , 'T' , 'C' , 'H' )) {
589639 parser -> method = HTTP_PROPPATCH ;
590640 break ;
@@ -637,6 +687,9 @@ size_t http_parser_execute (http_parser *parser,
637687 if (ch == ':' ) {
638688 state = s_req_schema_slash ;
639689 break ;
690+ } else if (ch == '.' ) {
691+ state = s_req_host ;
692+ break ;
640693 }
641694
642695 goto error ;
@@ -1156,12 +1209,14 @@ size_t http_parser_execute (http_parser *parser,
11561209
11571210 if (!c ) {
11581211 if (ch == CR ) {
1212+ CALLBACK (header_value );
11591213 header_state = h_general ;
11601214 state = s_header_almost_done ;
11611215 break ;
11621216 }
11631217
11641218 if (ch == LF ) {
1219+ CALLBACK (header_value );
11651220 state = s_header_field_start ;
11661221 break ;
11671222 }
@@ -1547,15 +1602,8 @@ void
15471602http_parser_init (http_parser * parser , enum http_parser_type t )
15481603{
15491604 parser -> type = t ;
1550- parser -> state = (t == HTTP_REQUEST ? s_start_req : s_start_res );
1605+ parser -> state = (t == HTTP_REQUEST ? s_start_req : ( t == HTTP_RESPONSE ? s_start_res : s_start_res_or_resp ) );
15511606 parser -> nread = 0 ;
15521607 parser -> upgrade = 0 ;
1553-
1554- parser -> header_field_mark = NULL ;
1555- parser -> header_value_mark = NULL ;
1556- parser -> query_string_mark = NULL ;
1557- parser -> path_mark = NULL ;
1558- parser -> url_mark = NULL ;
1559- parser -> fragment_mark = NULL ;
15601608}
15611609
0 commit comments