libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 9b39de8d9eb11807d13ff7fd8e7a27ab84c12454
parent 8c77370410297ae698a1b034da203fd567867203
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 10 Jul 2020 15:06:46 +0200

fix postprocessor parser issue discovered by MD

Diffstat:
MChangeLog | 3+++
Msrc/microhttpd/postprocessor.c | 48++++++++++++++++++++++++++++--------------------
Msrc/microhttpd/test_postprocessor.c | 2+-
Msrc/microhttpd/test_postprocessor_md.c | 25++++++++++++++++---------
4 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,6 @@ +Fri Jul 10 15:04:51 CEST 2020 + Fixed Postprocessor URL-encoded parsing if '%' fell on boundary. -CG/MD + Thu 02 Jul 2020 09:56:23 PM CEST Fixed return type of MHD_queue_basic_auth_fail_response. -CA/CG diff --git a/src/microhttpd/postprocessor.c b/src/microhttpd/postprocessor.c @@ -353,21 +353,17 @@ MHD_create_post_processor (struct MHD_Connection *connection, /** - * Give a (possibly partial) value to the - * application callback. We have some - * part of the value in the 'pp->xbuf', the - * rest is between @a value_start and @a value_end. - * If @a last_escape is non-NULL, there may be - * an incomplete escape sequence at at @a value_escape - * between @a value_start and @a value_end which - * we should preserve in 'pp->xbuf' for the future. + * Give a (possibly partial) value to the application callback. We have some + * part of the value in the 'pp->xbuf', the rest is between @a value_start and + * @a value_end. If @a last_escape is non-NULL, there may be an incomplete + * escape sequence at at @a value_escape between @a value_start and @a + * value_end which we should preserve in 'pp->xbuf' for the future. * - * Unescapes the value and calls the iterator - * together with the key. The key must already - * be in the key buffer allocated and 0-terminated - * at the end of @a pp at the time of the call. + * Unescapes the value and calls the iterator together with the key. The key + * must already be in the key buffer allocated and 0-terminated at the end of + * @a pp at the time of the call. * - * @param pp post processor to act upon + * @param[in,out] pp post processor to act upon * @param value_start where in memory is the value * @param value_end where does the value end * @param last_escape last '%'-sign in value range, @@ -404,6 +400,7 @@ process_value (struct MHD_PostProcessor *pp, (xoff > 0) ) { size_t delta = value_end - value_start; + bool cut = false; if (delta > XBUF_SIZE - xoff) delta = XBUF_SIZE - xoff; @@ -414,14 +411,23 @@ process_value (struct MHD_PostProcessor *pp, /* find if escape sequence is at the end of the processing buffer; if so, exclude those from processing (reduce delta to point at end of processed region) */ - if (delta >= XBUF_SIZE - 2) + if ( (xoff + delta > 0) && + ('%' == xbuf[xoff + delta - 1]) ) { - if ((xoff + delta > 0) && - ('%' == xbuf[xoff + delta - 1])) - delta--; - else if ((xoff + delta > 1) && - ('%' == xbuf[xoff + delta - 2])) - delta -= 2; + cut = (delta != XBUF_SIZE - xoff); + delta--; + pp->xbuf[0] = '%'; + pp->xbuf_pos = 1; + } + else if ( (xoff + delta > 1) && + ('%' == xbuf[xoff + delta - 2]) ) + { + memcpy (pp->xbuf, + &xbuf[xoff + delta - 2], + 2); + pp->xbuf_pos = 2; + cut = (delta != XBUF_SIZE - xoff); + delta -= 2; } xoff += delta; value_start += delta; @@ -447,6 +453,8 @@ process_value (struct MHD_PostProcessor *pp, } pp->value_offset += xoff; xoff = 0; + if (cut) + break; } } diff --git a/src/microhttpd/test_postprocessor.c b/src/microhttpd/test_postprocessor.c @@ -1,6 +1,6 @@ /* This file is part of libmicrohttpd - Copyright (C) 2007,2013,2019 Christian Grothoff + Copyright (C) 2007, 2013, 2019, 2020 Christian Grothoff libmicrohttpd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published diff --git a/src/microhttpd/test_postprocessor_md.c b/src/microhttpd/test_postprocessor_md.c @@ -114,13 +114,22 @@ post_data_iterator2 (void *cls, uint64_t off, size_t size) { - printf ("%s\t%s\n", key, data); + static char seen[16]; + + printf ("%s\t%s@ %llu\n", + key, + data, + (unsigned long long) off); if (0 == strcmp (key, "text")) { - if ( (10 != size) || - (0 != memcmp (data, "text, text", 10)) ) - exit (5); - found |= 1; + if (off + size > sizeof (seen)) + exit (6); + memcpy (&seen[off], + data, + size); + if ( (10 == off + size) && + (0 == memcmp (seen, "text, text", 10)) ) + found |= 1; } return MHD_YES; } @@ -151,7 +160,6 @@ main (int argc, char *argv[]) exit (3); if (found != 15) exit (2); - found = 0; postprocessor = malloc (sizeof (struct MHD_PostProcessor) + 0x1000 + 1); @@ -165,9 +173,8 @@ main (int argc, char *argv[]) postprocessor->buffer_size = 0x1000; postprocessor->state = PP_Init; postprocessor->skip_rn = RN_Inactive; - MHD_post_process (postprocessor, "text=text%2C+text", 11 + 6); - // MHD_post_process (postprocessor, "text=text%2", 11); - // MHD_post_process (postprocessor, "C+text", 6); + MHD_post_process (postprocessor, "text=text%2", 11); + MHD_post_process (postprocessor, "C+text", 6); MHD_post_process (postprocessor, "", 0); MHD_destroy_post_processor (postprocessor); if (found != 1)