From: Michal Nowak Date: Mon, 1 Jun 2026 14:37:12 +0000 (+0200) Subject: Sync picohttpparser.c with upstream commit a875a01 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cfd7fd867b56c11cf8fafabe057fd19785620c62;p=thirdparty%2Fbind9.git Sync picohttpparser.c with upstream commit a875a01 Pull in upstream commit a875a01 from h2o/picohttpparser: enforce use of CRLF in chunk headers, by rejecting bare CR / LF. Replaces the lenient CHUNKED_IN_CHUNK_CRLF state with strict CHUNKED_IN_CHUNK_HEADER_EXPECT_LF, CHUNKED_IN_CHUNK_DATA_EXPECT_CR and CHUNKED_IN_CHUNK_DATA_EXPECT_LF states. Synced with the h2o/picohttpparser upstream repository up to commit f4d94b48b31e0abae029ebeafcfd9ca0680ede58. This commit is just hygiene and consistency by keeping the vendored copy current. Assisted-by: Claude:claude-opus-4-7 --- diff --git a/lib/isc/picohttpparser.c b/lib/isc/picohttpparser.c index 89fb8b6aa3b..e008232f26c 100644 --- a/lib/isc/picohttpparser.c +++ b/lib/isc/picohttpparser.c @@ -2,8 +2,6 @@ * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase, * Shigeo Mitsunari * - * SPDX-License-Identifier: MIT - * * The software is licensed under either the MIT License (below) or the Perl * license. * @@ -161,12 +159,11 @@ get_token_to_eol(const char *buf, const char *buf_end, const char **token, /* 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(); @@ -444,7 +441,7 @@ phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *num_headers, size_t last_len) { const char *buf = buf_start, *buf_end = buf_start + len; size_t max_headers = *num_headers; - int r = -1; + int r; *method = NULL; *method_len = 0; @@ -580,8 +577,10 @@ phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, enum { CHUNKED_IN_CHUNK_SIZE, CHUNKED_IN_CHUNK_EXT, + CHUNKED_IN_CHUNK_HEADER_EXPECT_LF, CHUNKED_IN_CHUNK_DATA, - CHUNKED_IN_CHUNK_CRLF, + CHUNKED_IN_CHUNK_DATA_EXPECT_CR, + CHUNKED_IN_CHUNK_DATA_EXPECT_LF, CHUNKED_IN_TRAILERS_LINE_HEAD, CHUNKED_IN_TRAILERS_LINE_MIDDLE }; @@ -646,7 +645,7 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, } decoder->_hex_count = 0; decoder->_state = CHUNKED_IN_CHUNK_EXT; - /* fall through */ + /* fallthru */ case CHUNKED_IN_CHUNK_EXT: /* RFC 7230 A.2 "Line folding in chunk extensions is * disallowed" */ @@ -654,11 +653,25 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, if (src == bufsz) { goto Exit; } - if (buf[src] == '\012') { + if (buf[src] == '\015') { break; + } else if (buf[src] == '\012') { + ret = -1; + goto Exit; } } ++src; + decoder->_state = CHUNKED_IN_CHUNK_HEADER_EXPECT_LF; + /* fallthru */ + case CHUNKED_IN_CHUNK_HEADER_EXPECT_LF: + if (src == bufsz) { + goto Exit; + } + if (buf[src] != '\012') { + ret = -1; + goto Exit; + } + ++src; if (decoder->bytes_left_in_chunk == 0) { if (decoder->consume_trailer) { decoder->_state = @@ -669,7 +682,7 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, } } decoder->_state = CHUNKED_IN_CHUNK_DATA; - /* fall through */ + /* fallthru */ case CHUNKED_IN_CHUNK_DATA: { size_t avail = bufsz - src; if (avail < decoder->bytes_left_in_chunk) { @@ -688,17 +701,23 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, src += decoder->bytes_left_in_chunk; dst += decoder->bytes_left_in_chunk; decoder->bytes_left_in_chunk = 0; - decoder->_state = CHUNKED_IN_CHUNK_CRLF; + decoder->_state = CHUNKED_IN_CHUNK_DATA_EXPECT_CR; } - /* fall through */ - case CHUNKED_IN_CHUNK_CRLF: - for (;; ++src) { - if (src == bufsz) { - goto Exit; - } - if (buf[src] != '\015') { - break; - } + /* fallthru */ + case CHUNKED_IN_CHUNK_DATA_EXPECT_CR: + if (src == bufsz) { + goto Exit; + } + if (buf[src] != '\015') { + ret = -1; + goto Exit; + } + ++src; + decoder->_state = CHUNKED_IN_CHUNK_DATA_EXPECT_LF; + /* fallthru */ + case CHUNKED_IN_CHUNK_DATA_EXPECT_LF: + if (src == bufsz) { + goto Exit; } if (buf[src] != '\012') { ret = -1; @@ -720,7 +739,7 @@ phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, goto Complete; } decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE; - /* fall through */ + /* fallthru */ case CHUNKED_IN_TRAILERS_LINE_MIDDLE: for (;; ++src) { if (src == bufsz) {