From 1c2fb1ab74b88e8ac647f3c28d2158f418a80aa2 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. --- ext/standard/http_fopen_wrapper.c | 18 +++++------------- ext/standard/tests/http/bug78719.phpt | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 ext/standard/tests/http/bug78719.phpt diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index bf0363fd3cca4..4f702bf75f38b 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -732,24 +732,16 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* 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 0000000000000..b12bd3951e36f --- /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)