From 51e2015af3fc4757a666736aae7899a43f76ae6d Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 23 Feb 2021 15:32:54 +0100 Subject: [PATCH] Fix #78719: http wrapper silently ignores long Location headers When opening HTTP streams, and reading the headers, we currently discard header lines longer than `HTTP_HEADER_BLOCK_SIZE` (1024 bytes). While this is not generally forbidden by RFC 7230, section 3.2.5, it is not generally allowed either, since that may change the "message framing or response semantics". We thus fix this by allowing arbitrarily long header lines. Closes GH-6720. --- NEWS | 2 ++ ext/standard/http_fopen_wrapper.c | 18 +++++------------- ext/standard/tests/http/bug78719.phpt | 26 ++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 ext/standard/tests/http/bug78719.phpt diff --git a/NEWS b/NEWS index f2bd80397e..afd2514519 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ PHP NEWS - Standard: . Fixed bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI). (cmb) + . Fixed bug #78719 (http wrapper silently ignores long Location headers). + (cmb) 04 Mar 2021, php 7.4.16 diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index bf0363fd3c..4f702bf75f 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -732,24 +732,16 @@ finish: /* read past HTTP headers */ - http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE); - while (!php_stream_eof(stream)) { size_t http_header_line_length; - if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') { + if (http_header_line != NULL) { + efree(http_header_line); + } + if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') { char *e = http_header_line + http_header_line_length - 1; char *http_header_value; - if (*e != '\n') { - do { /* partial header */ - if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) { - php_stream_wrapper_log_error(wrapper, options, "Failed to read HTTP headers"); - goto out; - } - e = http_header_line + http_header_line_length - 1; - } while (*e != '\n'); - continue; - } + while (e >= http_header_line && (*e == '\n' || *e == '\r')) { e--; } diff --git a/ext/standard/tests/http/bug78719.phpt b/ext/standard/tests/http/bug78719.phpt new file mode 100644 index 0000000000..b12bd3951e --- /dev/null +++ b/ext/standard/tests/http/bug78719.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #78719 (http wrapper silently ignores long Location headers) +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + ['follow_location' => 0]]); +$stream = fopen('http://127.0.0.1:12342/', 'r', false, $context); +var_dump(stream_get_contents($stream)); +var_dump(stream_get_meta_data($stream)['wrapper_data'][1] === "Location: $url"); + +http_server_kill($pid); +?> +--EXPECTF-- +string(4) "Body" +bool(true) -- 2.50.1