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-