diff options
author | Christian Grothoff <christian@grothoff.org> | 2019-12-26 14:44:18 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2019-12-26 14:44:18 +0100 |
commit | f34781c87e48df6081eaf5defd1430f44013e8b6 (patch) | |
tree | c12fa15f398a2050d04f724e17df60f357948aac /src/microhttpd | |
parent | 55f715e15e3ce66babc939b5a670bee02d4d9571 (diff) | |
download | libmicrohttpd-f34781c87e48df6081eaf5defd1430f44013e8b6.tar.gz libmicrohttpd-f34781c87e48df6081eaf5defd1430f44013e8b6.zip |
add post processor logic fix
Diffstat (limited to 'src/microhttpd')
-rw-r--r-- | src/microhttpd/postprocessor.c | 63 | ||||
-rw-r--r-- | src/microhttpd/test_postprocessor.c | 56 |
2 files changed, 85 insertions, 34 deletions
diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c index e515b363..b7f6b108 100644 --- a/src/microhttpd/postprocessor.c +++ b/src/microhttpd/postprocessor.c | |||
@@ -215,9 +215,15 @@ struct MHD_PostProcessor | |||
215 | * Used to ensure that we do always call 'ikvi' even if the | 215 | * Used to ensure that we do always call 'ikvi' even if the |
216 | * payload is empty (but not more than once). | 216 | * payload is empty (but not more than once). |
217 | */ | 217 | */ |
218 | int must_ikvi; | 218 | bool must_ikvi; |
219 | 219 | ||
220 | /** | 220 | /** |
221 | * Set if we still need to run the unescape logic | ||
222 | * on the key allocated at the end of this struct. | ||
223 | */ | ||
224 | bool must_unescape_key; | ||
225 | |||
226 | /** | ||
221 | * State of the parser. | 227 | * State of the parser. |
222 | */ | 228 | */ |
223 | enum PP_State state; | 229 | enum PP_State state; |
@@ -395,6 +401,7 @@ process_value (struct MHD_PostProcessor *pp, | |||
395 | } | 401 | } |
396 | } | 402 | } |
397 | while ( (value_start != value_end) || | 403 | while ( (value_start != value_end) || |
404 | (pp->must_ikvi) || | ||
398 | (xoff > 0) ) | 405 | (xoff > 0) ) |
399 | { | 406 | { |
400 | size_t delta = value_end - value_start; | 407 | size_t delta = value_end - value_start; |
@@ -425,6 +432,7 @@ process_value (struct MHD_PostProcessor *pp, | |||
425 | MHD_unescape_plus (xbuf); | 432 | MHD_unescape_plus (xbuf); |
426 | xoff = MHD_http_unescape (xbuf); | 433 | xoff = MHD_http_unescape (xbuf); |
427 | /* finally: call application! */ | 434 | /* finally: call application! */ |
435 | pp->must_ikvi = false; | ||
428 | if (MHD_NO == pp->ikvi (pp->cls, | 436 | if (MHD_NO == pp->ikvi (pp->cls, |
429 | MHD_POSTDATA_KIND, | 437 | MHD_POSTDATA_KIND, |
430 | (const char *) &pp[1], /* key */ | 438 | (const char *) &pp[1], /* key */ |
@@ -466,7 +474,8 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
466 | const char *last_escape = NULL; | 474 | const char *last_escape = NULL; |
467 | 475 | ||
468 | poff = 0; | 476 | poff = 0; |
469 | while ( (poff < post_data_len) && | 477 | while ( ( (poff < post_data_len) || |
478 | (pp->state == PP_Callback) ) && | ||
470 | (pp->state != PP_Error) ) | 479 | (pp->state != PP_Error) ) |
471 | { | 480 | { |
472 | switch (pp->state) { | 481 | switch (pp->state) { |
@@ -478,6 +487,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
478 | /* key phase */ | 487 | /* key phase */ |
479 | if (NULL == start_key) | 488 | if (NULL == start_key) |
480 | start_key = &post_data[poff]; | 489 | start_key = &post_data[poff]; |
490 | pp->must_ikvi = true; | ||
481 | switch (post_data[poff]) | 491 | switch (post_data[poff]) |
482 | { | 492 | { |
483 | case '=': | 493 | case '=': |
@@ -519,13 +529,27 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
519 | /* case 'value&' */ | 529 | /* case 'value&' */ |
520 | end_value = &post_data[poff]; | 530 | end_value = &post_data[poff]; |
521 | poff++; | 531 | poff++; |
522 | pp->state = PP_Callback; | 532 | if ( pp->must_ikvi || |
533 | (start_value != end_value) ) | ||
534 | { | ||
535 | pp->state = PP_Callback; | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | pp->buffer_pos = 0; | ||
540 | pp->value_offset = 0; | ||
541 | pp->state = PP_Init; | ||
542 | } | ||
543 | continue; | ||
523 | case '\n': | 544 | case '\n': |
524 | case '\r': | 545 | case '\r': |
525 | /* Case: 'value\n' or 'value\r' */ | 546 | /* Case: 'value\n' or 'value\r' */ |
526 | end_value = &post_data[poff]; | 547 | end_value = &post_data[poff]; |
527 | poff++; | 548 | poff++; |
528 | pp->state = PP_Done; | 549 | if (pp->must_ikvi) |
550 | pp->state = PP_Callback; | ||
551 | else | ||
552 | pp->state = PP_Done; | ||
529 | break; | 553 | break; |
530 | case '%': | 554 | case '%': |
531 | last_escape = &post_data[poff]; | 555 | last_escape = &post_data[poff]; |
@@ -564,7 +588,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
564 | case PP_Callback: | 588 | case PP_Callback: |
565 | if ( (pp->buffer_pos + (end_key - start_key) > | 589 | if ( (pp->buffer_pos + (end_key - start_key) > |
566 | pp->buffer_size) || | 590 | pp->buffer_size) || |
567 | (pp->buffer_pos + (end_key - start_key) > | 591 | (pp->buffer_pos + (end_key - start_key) < |
568 | pp->buffer_pos) ) | 592 | pp->buffer_pos) ) |
569 | { | 593 | { |
570 | /* key too long, cannot parse! */ | 594 | /* key too long, cannot parse! */ |
@@ -580,9 +604,14 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
580 | pp->buffer_pos += end_key - start_key; | 604 | pp->buffer_pos += end_key - start_key; |
581 | start_key = NULL; | 605 | start_key = NULL; |
582 | end_key = NULL; | 606 | end_key = NULL; |
607 | pp->must_unescape_key = true; | ||
608 | } | ||
609 | if (pp->must_unescape_key) | ||
610 | { | ||
583 | kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */ | 611 | kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */ |
584 | MHD_unescape_plus (kbuf); | 612 | MHD_unescape_plus (kbuf); |
585 | MHD_http_unescape (kbuf); | 613 | MHD_http_unescape (kbuf); |
614 | pp->must_unescape_key = false; | ||
586 | } | 615 | } |
587 | process_value (pp, | 616 | process_value (pp, |
588 | start_value, | 617 | start_value, |
@@ -591,6 +620,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
591 | pp->value_offset = 0; | 620 | pp->value_offset = 0; |
592 | start_value = NULL; | 621 | start_value = NULL; |
593 | end_value = NULL; | 622 | end_value = NULL; |
623 | pp->buffer_pos = 0; | ||
594 | pp->state = PP_Init; | 624 | pp->state = PP_Init; |
595 | break; | 625 | break; |
596 | default: | 626 | default: |
@@ -602,8 +632,7 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
602 | } | 632 | } |
603 | 633 | ||
604 | /* save remaining data for next iteration */ | 634 | /* save remaining data for next iteration */ |
605 | if ( (NULL != start_key) && | 635 | if (NULL != start_key) |
606 | (PP_Init == pp->state) ) | ||
607 | { | 636 | { |
608 | if (NULL == end_key) | 637 | if (NULL == end_key) |
609 | end_key = &post_data[poff]; | 638 | end_key = &post_data[poff]; |
@@ -611,22 +640,20 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
611 | start_key, | 640 | start_key, |
612 | end_key - start_key); | 641 | end_key - start_key); |
613 | pp->buffer_pos += end_key - start_key; | 642 | pp->buffer_pos += end_key - start_key; |
643 | pp->must_unescape_key = true; | ||
644 | start_key = NULL; | ||
645 | end_key = NULL; | ||
614 | } | 646 | } |
615 | if ( (NULL != start_value) && | 647 | if ( (NULL != start_value) && |
616 | (PP_ProcessValue == pp->state) ) | 648 | (PP_ProcessValue == pp->state) ) |
617 | { | 649 | { |
618 | /* compute key, if we have not already */ | 650 | /* compute key, if we have not already */ |
619 | if (NULL != start_key) | 651 | if (pp->must_unescape_key) |
620 | { | 652 | { |
621 | memcpy (&kbuf[pp->buffer_pos], | ||
622 | start_key, | ||
623 | end_key - start_key); | ||
624 | pp->buffer_pos += end_key - start_key; | ||
625 | start_key = NULL; | ||
626 | end_key = NULL; | ||
627 | kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */ | 653 | kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */ |
628 | MHD_unescape_plus (kbuf); | 654 | MHD_unescape_plus (kbuf); |
629 | MHD_http_unescape (kbuf); | 655 | MHD_http_unescape (kbuf); |
656 | pp->must_unescape_key = false; | ||
630 | } | 657 | } |
631 | if (NULL == end_value) | 658 | if (NULL == end_value) |
632 | end_value = &post_data[poff]; | 659 | end_value = &post_data[poff]; |
@@ -634,8 +661,8 @@ post_process_urlencoded (struct MHD_PostProcessor *pp, | |||
634 | start_value, | 661 | start_value, |
635 | end_value, | 662 | end_value, |
636 | last_escape); | 663 | last_escape); |
664 | pp->must_ikvi = false; | ||
637 | } | 665 | } |
638 | |||
639 | return MHD_YES; | 666 | return MHD_YES; |
640 | } | 667 | } |
641 | 668 | ||
@@ -953,7 +980,7 @@ process_value_to_boundary (struct MHD_PostProcessor *pp, | |||
953 | /* newline is either at beginning of boundary or | 980 | /* newline is either at beginning of boundary or |
954 | at least at the last character that we are sure | 981 | at least at the last character that we are sure |
955 | is not part of the boundary */ | 982 | is not part of the boundary */ |
956 | if ( ( (MHD_YES == pp->must_ikvi) || | 983 | if ( ( (pp->must_ikvi) || |
957 | (0 != newline) ) && | 984 | (0 != newline) ) && |
958 | (MHD_NO == pp->ikvi (pp->cls, | 985 | (MHD_NO == pp->ikvi (pp->cls, |
959 | MHD_POSTDATA_KIND, | 986 | MHD_POSTDATA_KIND, |
@@ -968,7 +995,7 @@ process_value_to_boundary (struct MHD_PostProcessor *pp, | |||
968 | pp->state = PP_Error; | 995 | pp->state = PP_Error; |
969 | return MHD_NO; | 996 | return MHD_NO; |
970 | } | 997 | } |
971 | pp->must_ikvi = MHD_NO; | 998 | pp->must_ikvi = false; |
972 | pp->value_offset += newline; | 999 | pp->value_offset += newline; |
973 | (*ioffptr) += newline; | 1000 | (*ioffptr) += newline; |
974 | return MHD_YES; | 1001 | return MHD_YES; |
@@ -1155,7 +1182,7 @@ post_process_multipart (struct MHD_PostProcessor *pp, | |||
1155 | } | 1182 | } |
1156 | break; | 1183 | break; |
1157 | case PP_ProcessEntryHeaders: | 1184 | case PP_ProcessEntryHeaders: |
1158 | pp->must_ikvi = MHD_YES; | 1185 | pp->must_ikvi = true; |
1159 | if (MHD_NO == | 1186 | if (MHD_NO == |
1160 | process_multipart_headers (pp, | 1187 | process_multipart_headers (pp, |
1161 | &ioff, | 1188 | &ioff, |
diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c index 4b0c9e07..2c37565c 100644 --- a/src/microhttpd/test_postprocessor.c +++ b/src/microhttpd/test_postprocessor.c | |||
@@ -80,6 +80,7 @@ const char *want[] = { | |||
80 | NULL, NULL, NULL, NULL, NULL | 80 | NULL, NULL, NULL, NULL, NULL |
81 | }; | 81 | }; |
82 | 82 | ||
83 | |||
83 | static int | 84 | static int |
84 | mismatch (const char *a, const char *b) | 85 | mismatch (const char *a, const char *b) |
85 | { | 86 | { |
@@ -98,7 +99,9 @@ value_checker (void *cls, | |||
98 | const char *filename, | 99 | const char *filename, |
99 | const char *content_type, | 100 | const char *content_type, |
100 | const char *transfer_encoding, | 101 | const char *transfer_encoding, |
101 | const char *data, uint64_t off, size_t size) | 102 | const char *data, |
103 | uint64_t off, | ||
104 | size_t size) | ||
102 | { | 105 | { |
103 | int *want_off = cls; | 106 | int *want_off = cls; |
104 | int idx = *want_off; | 107 | int idx = *want_off; |
@@ -106,20 +109,27 @@ value_checker (void *cls, | |||
106 | 109 | ||
107 | #if 0 | 110 | #if 0 |
108 | fprintf (stderr, | 111 | fprintf (stderr, |
109 | "VC: `%s' `%s' `%s' `%s' `%.*s'\n", | 112 | "VC: `%s' `%s' `%s' `%s' `%.*s' (%d)\n", |
110 | key, filename, content_type, transfer_encoding, | 113 | key, filename, content_type, transfer_encoding, |
111 | (int) size, | 114 | (int) size, |
112 | data); | 115 | data, |
116 | (int) size); | ||
113 | #endif | 117 | #endif |
114 | if ( (0 != off) && (0 == size) ) | 118 | if ( (0 != off) && (0 == size) ) |
119 | { | ||
120 | if (NULL == want[idx + 4]) | ||
121 | *want_off = idx + 5; | ||
115 | return MHD_YES; | 122 | return MHD_YES; |
123 | } | ||
116 | if ((idx < 0) || | 124 | if ((idx < 0) || |
117 | (want[idx] == NULL) || | 125 | (want[idx] == NULL) || |
118 | (0 != strcmp (key, want[idx])) || | 126 | (0 != strcmp (key, want[idx])) || |
119 | (mismatch (filename, want[idx + 1])) || | 127 | (mismatch (filename, want[idx + 1])) || |
120 | (mismatch (content_type, want[idx + 2])) || | 128 | (mismatch (content_type, want[idx + 2])) || |
121 | (mismatch (transfer_encoding, want[idx + 3])) || | 129 | (mismatch (transfer_encoding, want[idx + 3])) || |
122 | (0 != memcmp (data, &want[idx + 4][off], size))) | 130 | (0 != memcmp (data, |
131 | &want[idx + 4][off], | ||
132 | size))) | ||
123 | { | 133 | { |
124 | *want_off = -1; | 134 | *want_off = -1; |
125 | fprintf (stderr, | 135 | fprintf (stderr, |
@@ -128,18 +138,26 @@ value_checker (void *cls, | |||
128 | (int) size, | 138 | (int) size, |
129 | data); | 139 | data); |
130 | fprintf (stderr, | 140 | fprintf (stderr, |
141 | "Wanted: `%s' `%s' `%s' `%s' `%s'\n", | ||
142 | want[idx], | ||
143 | want[idx+1], | ||
144 | want[idx+2], | ||
145 | want[idx+3], | ||
146 | want[idx+4]); | ||
147 | fprintf (stderr, | ||
131 | "Unexpected result: %d/%d/%d/%d/%d/%d/%d\n", | 148 | "Unexpected result: %d/%d/%d/%d/%d/%d/%d\n", |
132 | (idx < 0), | 149 | (idx < 0), |
133 | (want[idx] == NULL), | 150 | (want[idx] == NULL), |
134 | (0 != strcmp (key, want[idx])), | 151 | (NULL != want[idx]) && (0 != strcmp (key, want[idx])), |
135 | (mismatch (filename, want[idx + 1])), | 152 | (mismatch (filename, want[idx + 1])), |
136 | (mismatch (content_type, want[idx + 2])), | 153 | (mismatch (content_type, want[idx + 2])), |
137 | (mismatch (transfer_encoding, want[idx + 3])), | 154 | (mismatch (transfer_encoding, want[idx + 3])), |
138 | (0 != memcmp (data, &want[idx + 4][off], size))); | 155 | (0 != memcmp (data, &want[idx + 4][off], size))); |
139 | |||
140 | return MHD_NO; | 156 | return MHD_NO; |
141 | } | 157 | } |
142 | if (off + size == strlen (want[idx + 4])) | 158 | if ( ( (NULL == want[idx+4]) && |
159 | (0 == off + size) ) || | ||
160 | (off + size == strlen (want[idx + 4])) ) | ||
143 | *want_off = idx + 5; | 161 | *want_off = idx + 5; |
144 | return MHD_YES; | 162 | return MHD_YES; |
145 | } | 163 | } |
@@ -185,8 +203,10 @@ test_urlencoding_case (unsigned int want_start, | |||
185 | if (want_off != want_end) | 203 | if (want_off != want_end) |
186 | { | 204 | { |
187 | fprintf (stderr, | 205 | fprintf (stderr, |
188 | "Test failed in line %u\n", | 206 | "Test failed in line %u: %u != %u\n", |
189 | (unsigned int) __LINE__); | 207 | (unsigned int) __LINE__, |
208 | want_off, | ||
209 | want_end); | ||
190 | return 1; | 210 | return 1; |
191 | } | 211 | } |
192 | return 0; | 212 | return 0; |
@@ -198,17 +218,20 @@ test_urlencoding (void) | |||
198 | { | 218 | { |
199 | unsigned int errorCount = 0; | 219 | unsigned int errorCount = 0; |
200 | 220 | ||
201 | errorCount += test_urlencoding_case (URL_START, URL_END, URL_DATA); | 221 | errorCount += test_urlencoding_case (URL_START, |
222 | URL_END, | ||
223 | URL_DATA); | ||
202 | errorCount += test_urlencoding_case (URL_NOVALUE1_START, | 224 | errorCount += test_urlencoding_case (URL_NOVALUE1_START, |
203 | URL_NOVALUE1_END, | 225 | URL_NOVALUE1_END, |
204 | URL_NOVALUE1_DATA); | 226 | URL_NOVALUE1_DATA); |
205 | errorCount += test_urlencoding_case (URL_NOVALUE2_START, | 227 | errorCount += test_urlencoding_case (URL_NOVALUE2_START, |
206 | URL_NOVALUE2_END, | 228 | URL_NOVALUE2_END, |
207 | URL_NOVALUE2_DATA); | 229 | URL_NOVALUE2_DATA); |
208 | fprintf (stderr, | 230 | if (0 != errorCount) |
209 | "Test failed in line %u with %u errors\n", | 231 | fprintf (stderr, |
210 | (unsigned int) __LINE__, | 232 | "Test failed in line %u with %u errors\n", |
211 | errorCount); | 233 | (unsigned int) __LINE__, |
234 | errorCount); | ||
212 | return errorCount; | 235 | return errorCount; |
213 | } | 236 | } |
214 | 237 | ||
@@ -419,8 +442,9 @@ test_empty_value (void) | |||
419 | if (want_off != URL_EMPTY_VALUE_END) | 442 | if (want_off != URL_EMPTY_VALUE_END) |
420 | { | 443 | { |
421 | fprintf (stderr, | 444 | fprintf (stderr, |
422 | "Test failed in line %u\n", | 445 | "Test failed in line %u at offset %d\n", |
423 | (unsigned int) __LINE__); | 446 | (unsigned int) __LINE__, |
447 | (int) want_off); | ||
424 | return 8; | 448 | return 8; |
425 | } | 449 | } |
426 | return 0; | 450 | return 0; |