Skip to content

Commit 51e2015

Browse files
committed
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.
1 parent 71297a2 commit 51e2015

File tree

3 files changed

+33
-13
lines changed

3 files changed

+33
-13
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ PHP NEWS
2626

2727
- Standard:
2828
. Fixed bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI). (cmb)
29+
. Fixed bug #78719 (http wrapper silently ignores long Location headers).
30+
(cmb)
2931

3032
04 Mar 2021, php 7.4.16
3133

ext/standard/http_fopen_wrapper.c

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -732,24 +732,16 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper,
732732

733733
/* read past HTTP headers */
734734

735-
http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);
736-
737735
while (!php_stream_eof(stream)) {
738736
size_t http_header_line_length;
739737

740-
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') {
738+
if (http_header_line != NULL) {
739+
efree(http_header_line);
740+
}
741+
if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') {
741742
char *e = http_header_line + http_header_line_length - 1;
742743
char *http_header_value;
743-
if (*e != '\n') {
744-
do { /* partial header */
745-
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
746-
php_stream_wrapper_log_error(wrapper, options, "Failed to read HTTP headers");
747-
goto out;
748-
}
749-
e = http_header_line + http_header_line_length - 1;
750-
} while (*e != '\n');
751-
continue;
752-
}
744+
753745
while (e >= http_header_line && (*e == '\n' || *e == '\r')) {
754746
e--;
755747
}

ext/standard/tests/http/bug78719.phpt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Bug #78719 (http wrapper silently ignores long Location headers)
3+
--SKIPIF--
4+
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
5+
--INI--
6+
allow_url_fopen=1
7+
--FILE--
8+
<?php
9+
require 'server.inc';
10+
11+
$url = str_repeat('*', 2000);
12+
$responses = array(
13+
"data://text/plain,HTTP/1.0 302 Ok\r\nLocation: $url\r\n\r\nBody",
14+
);
15+
$pid = http_server("tcp://127.0.0.1:12342", $responses, $output);
16+
17+
$context = stream_context_create(['http' => ['follow_location' => 0]]);
18+
$stream = fopen('http://127.0.0.1:12342/', 'r', false, $context);
19+
var_dump(stream_get_contents($stream));
20+
var_dump(stream_get_meta_data($stream)['wrapper_data'][1] === "Location: $url");
21+
22+
http_server_kill($pid);
23+
?>
24+
--EXPECTF--
25+
string(4) "Body"
26+
bool(true)

0 commit comments

Comments
 (0)