]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Sync picohttpparser.c with upstream commit a875a01
authorMichal Nowak <mnowak@isc.org>
Mon, 1 Jun 2026 14:37:12 +0000 (16:37 +0200)
committerOndřej Surý <ondrej@isc.org>
Thu, 18 Jun 2026 04:26:07 +0000 (06:26 +0200)
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
lib/isc/picohttpparser.c

index 89fb8b6aa3bf4ea2652ad31265d25ac1646291ab..e008232f26cc28a128cb3d35b02fd10784d9c1e6 100644 (file)
@@ -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) {