aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-12-26 14:44:18 +0100
committerChristian Grothoff <christian@grothoff.org>2019-12-26 14:44:18 +0100
commitf34781c87e48df6081eaf5defd1430f44013e8b6 (patch)
treec12fa15f398a2050d04f724e17df60f357948aac /src/microhttpd
parent55f715e15e3ce66babc939b5a670bee02d4d9571 (diff)
downloadlibmicrohttpd-f34781c87e48df6081eaf5defd1430f44013e8b6.tar.gz
libmicrohttpd-f34781c87e48df6081eaf5defd1430f44013e8b6.zip
add post processor logic fix
Diffstat (limited to 'src/microhttpd')
-rw-r--r--src/microhttpd/postprocessor.c63
-rw-r--r--src/microhttpd/test_postprocessor.c56
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
83static int 84static int
84mismatch (const char *a, const char *b) 85mismatch (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;