From 43f7642e5d8f3d645601ab0b359eb49570c149b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Fri, 6 Dec 2024 18:29:39 +0100 Subject: [PATCH] Update picohttpparser.{c,h} with upstream repository Upstream code doesn't do regular releases, so we need to regularly sync the code from the upstream repository. This is synchronization up to the commit f8d0513 from Jan 29, 2024. (cherry picked from commit d14a76e115479eb8018a3856a3737a75aa8fa029) --- lib/isc/picohttpparser.c | 39 +++++++++++++++++++++++++++++++++------ lib/isc/picohttpparser.h | 3 +++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/isc/picohttpparser.c b/lib/isc/picohttpparser.c index 59f5ff1a18..ba1d291343 100644 --- a/lib/isc/picohttpparser.c +++ b/lib/isc/picohttpparser.c @@ -154,17 +154,19 @@ get_token_to_eol(const char *buf, const char *buf_end, const char **token, "\177\177"; /* allow chars w. MSB set */ int found; buf = findchar_fast(buf, buf_end, ranges1, 6, &found); - if (found) + if (found) { goto FOUND_CTL; + } #else /* find non-printable char within the next 8 bytes, this is the hottest * code; manually inlined */ while (likely(buf_end - buf >= 8)) { -#define DOIT() \ - do { \ - if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \ - goto NonPrintable; \ - ++buf; \ +#define DOIT() \ + do { \ + if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \ + goto NonPrintable; \ + } \ + ++buf; \ } while (0) DOIT(); DOIT(); @@ -603,6 +605,8 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t dst = 0, src = 0, bufsz = *_bufsz; ssize_t ret = -2; /* incomplete */ + decoder->_total_read += bufsz; + while (1) { switch (decoder->_state) { case CHUNKED_IN_CHUNK_SIZE: @@ -615,6 +619,20 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, ret = -1; goto Exit; } + /* the only characters that may appear + * after the chunk size are BWS, + * semicolon, or CRLF */ + switch (buf[src]) { + case ' ': + case '\011': + case ';': + case '\012': + case '\015': + break; + default: + ret = -1; + goto Exit; + } break; } if (decoder->_hex_count == sizeof(size_t) * 2) { @@ -714,6 +732,15 @@ Exit: if (dst != src) memmove(buf + dst, buf + src, bufsz - src); *_bufsz = dst; + /* if incomplete but the overhead of the chunked encoding is >=100KB and + * >80%, signal an error */ + if (ret == -2) { + decoder->_total_overhead += bufsz - dst; + if (decoder->_total_overhead >= 100 * 1024 && + decoder->_total_read - decoder->_total_overhead < + decoder->_total_read / 4) + ret = -1; + } return ret; } diff --git a/lib/isc/picohttpparser.h b/lib/isc/picohttpparser.h index 0657cb29c4..27df3b92d9 100644 --- a/lib/isc/picohttpparser.h +++ b/lib/isc/picohttpparser.h @@ -29,6 +29,7 @@ #ifndef picohttpparser_h #define picohttpparser_h +#include #include #ifdef _MSC_VER @@ -74,6 +75,8 @@ struct phr_chunked_decoder { char consume_trailer; /* if trailing headers should be consumed */ char _hex_count; char _state; + uint64_t _total_read; + uint64_t _total_overhead; }; /* the function rewrites the buffer given as (buf, bufsz) removing the chunked-