1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
From: Patrick Griffis <pgriffis@igalia.com>
Date: Mon, 8 Jul 2024 12:33:15 -0500
Subject: headers: Strictly don't allow NUL bytes
In the past (2015) this was allowed for some problematic sites. However Chromium also does not allow NUL bytes in either header names or values these days. So this should no longer be a problem.
(cherry picked from commit 04df03bc092ac20607f3e150936624d4f536e68b)
---
libsoup/soup-headers.c | 15 +++--------
tests/header-parsing-test.c | 62 ++++++++++++++++++++-------------------------
2 files changed, 32 insertions(+), 45 deletions(-)
diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c
index eec28ad..e5d3c03 100644
--- a/libsoup/soup-headers.c
+++ b/libsoup/soup-headers.c
@@ -50,13 +50,14 @@ soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest)
* ignorable trailing whitespace.
*/
+ /* No '\0's are allowed */
+ if (memchr (str, '\0', len))
+ return FALSE;
+
/* Skip over the Request-Line / Status-Line */
headers_start = memchr (str, '\n', len);
if (!headers_start)
return FALSE;
- /* No '\0's in the Request-Line / Status-Line */
- if (memchr (str, '\0', headers_start - str))
- return FALSE;
/* We work on a copy of the headers, which we can write '\0's
* into, so that we don't have to individually g_strndup and
@@ -68,14 +69,6 @@ soup_headers_parse (const char *str, int len, SoupMessageHeaders *dest)
headers_copy[copy_len] = '\0';
value_end = headers_copy;
- /* There shouldn't be any '\0's in the headers already, but
- * this is the web we're talking about.
- */
- while ((p = memchr (headers_copy, '\0', copy_len))) {
- memmove (p, p + 1, copy_len - (p - headers_copy));
- copy_len--;
- }
-
while (*(value_end + 1)) {
name = value_end + 1;
name_end = strchr (name, ':');
diff --git a/tests/header-parsing-test.c b/tests/header-parsing-test.c
index 946f118..e7d5e64 100644
--- a/tests/header-parsing-test.c
+++ b/tests/header-parsing-test.c
@@ -358,24 +358,6 @@ static struct RequestTest {
}
},
- { "NUL in header name", "760832",
- "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36,
- SOUP_STATUS_OK,
- "GET", "/", SOUP_HTTP_1_1,
- { { "Host", "example.com" },
- { NULL }
- }
- },
-
- { "NUL in header value", "760832",
- "GET / HTTP/1.1\r\nHost: example\x00" "com\r\n", 35,
- SOUP_STATUS_OK,
- "GET", "/", SOUP_HTTP_1_1,
- { { "Host", "examplecom" },
- { NULL }
- }
- },
-
/************************/
/*** INVALID REQUESTS ***/
/************************/
@@ -448,6 +430,21 @@ static struct RequestTest {
SOUP_STATUS_EXPECTATION_FAILED,
NULL, NULL, -1,
{ { NULL } }
+ },
+
+ // https://gitlab.gnome.org/GNOME/libsoup/-/issues/377
+ { "NUL in header name", NULL,
+ "GET / HTTP/1.1\r\nHost\x00: example.com\r\n", 36,
+ SOUP_STATUS_BAD_REQUEST,
+ NULL, NULL, -1,
+ { { NULL } }
+ },
+
+ { "NUL in header value", NULL,
+ "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28,
+ SOUP_STATUS_BAD_REQUEST,
+ NULL, NULL, -1,
+ { { NULL } }
}
};
static const int num_reqtests = G_N_ELEMENTS (reqtests);
@@ -620,22 +617,6 @@ static struct ResponseTest {
{ NULL } }
},
- { "NUL in header name", "760832",
- "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28,
- SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK",
- { { "Foo", "bar" },
- { NULL }
- }
- },
-
- { "NUL in header value", "760832",
- "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28,
- SOUP_HTTP_1_1, SOUP_STATUS_OK, "OK",
- { { "Foo", "bar" },
- { NULL }
- }
- },
-
/********************************/
/*** VALID CONTINUE RESPONSES ***/
/********************************/
@@ -768,6 +749,19 @@ static struct ResponseTest {
{ { NULL }
}
},
+
+ // https://gitlab.gnome.org/GNOME/libsoup/-/issues/377
+ { "NUL in header name", NULL,
+ "HTTP/1.1 200 OK\r\nF\x00oo: bar\r\n", 28,
+ -1, 0, NULL,
+ { { NULL } }
+ },
+
+ { "NUL in header value", "760832",
+ "HTTP/1.1 200 OK\r\nFoo: b\x00" "ar\r\n", 28,
+ -1, 0, NULL,
+ { { NULL } }
+ },
};
static const int num_resptests = G_N_ELEMENTS (resptests);
|