Blob Blame History Raw
diff -up libsoup-2.48.1/libsoup/soup-headers.c.nul-in-headers libsoup-2.48.1/libsoup/soup-headers.c
--- libsoup-2.48.1/libsoup/soup-headers.c.nul-in-headers	2014-11-30 16:32:58.000000000 +0100
+++ libsoup-2.48.1/libsoup/soup-headers.c	2016-04-13 09:05:32.947147115 +0200
@@ -35,17 +35,12 @@ soup_headers_parse (const char *str, int
 	const char *headers_start;
 	char *headers_copy, *name, *name_end, *value, *value_end;
 	char *eol, *sol, *p;
+	gsize copy_len;
 	gboolean success = FALSE;
 
 	g_return_val_if_fail (str != NULL, FALSE);
 	g_return_val_if_fail (dest != NULL, FALSE);
 
-	/* RFC 2616 does allow NUL bytes in the headers, but httpbis
-	 * is changing that, and we can't deal with them anyway.
-	 */
-	if (memchr (str, '\0', len))
-		return FALSE;
-
 	/* As per RFC 2616 section 19.3, we treat '\n' as the
 	 * line terminator, and '\r', if it appears, merely as
 	 * ignorable trailing whitespace.
@@ -55,14 +50,28 @@ soup_headers_parse (const char *str, int
 	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
 	 * then g_free each header name and value.
 	 */
-	headers_copy = g_strndup (headers_start, len - (headers_start - str));
+	copy_len = len - (headers_start - str);
+	headers_copy = g_malloc (copy_len + 1);
+	memcpy (headers_copy, headers_start, copy_len);
+	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 -up libsoup-2.48.1/tests/header-parsing.c.nul-in-headers libsoup-2.48.1/tests/header-parsing.c
--- libsoup-2.48.1/tests/header-parsing.c.nul-in-headers	2014-12-07 15:55:22.000000000 +0100
+++ libsoup-2.48.1/tests/header-parsing.c	2016-04-13 09:09:15.631137526 +0200
@@ -358,6 +358,24 @@ 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 ***/
 	/************************/
@@ -418,20 +436,6 @@ static struct RequestTest {
 	  { { NULL } }
 	},
 
-	{ "NUL in header name", "666316",
-	  "GET / HTTP/1.1\r\n\x00: silly\r\n", 37,
-	  SOUP_STATUS_BAD_REQUEST,
-	  NULL, NULL, -1,
-	  { { NULL } }
-	},
-
-	{ "NUL in header value", NULL,
-	  "GET / HTTP/1.1\r\nHost: example\x00com\r\n", 37,
-	  SOUP_STATUS_BAD_REQUEST,
-	  NULL, NULL, -1,
-	  { { NULL } }
-	},
-
 	{ "No terminating CRLF", NULL,
 	  "GET / HTTP/1.1\r\nHost: example.com", -1,
 	  SOUP_STATUS_BAD_REQUEST,
@@ -608,6 +612,22 @@ 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 }
+	  }
+	},
+
 	/*************************/
 	/*** INVALID RESPONSES ***/
 	/*************************/
@@ -677,18 +697,6 @@ static struct ResponseTest {
 	  -1, 0, NULL,
 	  { { NULL } }
 	},
-
-	{ "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", NULL,
-	  "HTTP/1.1 200 OK\r\nFoo: b\x00ar\r\n", 28,
-	  -1, 0, NULL,
-	  { { NULL } }
-	},
 };
 static const int num_resptests = G_N_ELEMENTS (resptests);