summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS4
-rw-r--r--ext/standard/http_fopen_wrapper.c18
-rw-r--r--ext/standard/tests/http/bug73297.phpt33
3 files changed, 55 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index b4c3249efa..02c8d33e24 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,10 @@ PHP NEWS
- SQLite3:
. Fixed bug #73530 (Unsetting result set may reset other result set). (cmb)
+- Standard:
+ . Fixed bug #73297 (HTTP stream wrapper should ignore HTTP 100 Continue).
+ (rowan dot collins at gmail dot com)
+
- XML:
. Fixed bug #72135 (malformed XML causes fault) (edgarsandi)
diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c
index 02b580fa28..f5f338c144 100644
--- a/ext/standard/http_fopen_wrapper.c
+++ b/ext/standard/http_fopen_wrapper.c
@@ -697,6 +697,24 @@ finish:
if ((options & STREAM_ONLY_GET_HEADERS) || ignore_errors) {
reqok = 1;
}
+
+ /* status codes of 1xx are "informational", and will be followed by a real response
+ * e.g "100 Continue". RFC 7231 states that unexpected 1xx status MUST be parsed,
+ * and MAY be ignored. As such, we need to skip ahead to the "real" status*/
+ if (response_code >= 100 && response_code < 200) {
+ /* consume lines until we find a line starting 'HTTP/1' */
+ while (
+ !php_stream_eof(stream)
+ && php_stream_get_line(stream, tmp_line, sizeof(tmp_line) - 1, &tmp_line_len) != NULL
+ && ( tmp_line_len < sizeof("HTTP/1") - 1 || strncasecmp(tmp_line, "HTTP/1", sizeof("HTTP/1") - 1) )
+ );
+
+ if (tmp_line_len > 9) {
+ response_code = atoi(tmp_line + 9);
+ } else {
+ response_code = 0;
+ }
+ }
/* all status codes in the 2xx range are defined by the specification as successful;
* all status codes in the 3xx range are for redirection, and so also should never
* fail */
diff --git a/ext/standard/tests/http/bug73297.phpt b/ext/standard/tests/http/bug73297.phpt
new file mode 100644
index 0000000000..0b0e02f3fd
--- /dev/null
+++ b/ext/standard/tests/http/bug73297.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #73297 (Ignore 100 Continue returned by HTTP/1.1 servers)
+--INI--
+allow_url_fopen=1
+--SKIPIF--
+<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
+--FILE--
+<?php
+require 'server.inc';
+
+$options = [
+ 'http' => [
+ 'protocol_version' => '1.1',
+ 'header' => 'Connection: Close'
+ ],
+];
+
+$ctx = stream_context_create($options);
+
+$responses = [
+ "data://text/plain,HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\n\r\n"
+ . "Hello"
+];
+$pid = http_server('tcp://127.0.0.1:12342', $responses);
+
+echo file_get_contents('http://127.0.0.1:12342/', false, $ctx);
+echo "\n";
+
+http_server_kill($pid);
+
+?>
+--EXPECT--
+Hello