From 0e097f2c96ce31b16fa371981045f224e5a37160 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 17 Nov 2017 23:11:15 +0100 Subject: [PATCH] Fixed bug #75535 The sizeof()s for Content-Length and Transfer-Encoding were missing the trailing ":". Apart from being generally wrong, this no longer verified that the header actually contains a colon, leading to the null http_header_value being used. Additionally, in the interest of being defensive, also make sure that http_header_value is non-null by setting it to the end of the header line (effectively an empty string) if there is no colon. If the following conditions are correct, this value is not going to be used though. --- NEWS | 4 ++++ ext/standard/http_fopen_wrapper.c | 8 +++++-- ext/standard/tests/http/bug75535.phpt | 31 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/http/bug75535.phpt diff --git a/NEWS b/NEWS index fa35c56c1bd..57d0fdb9736 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ PHP NEWS . Fixed bug #75384 (PHP seems incompatible with OneDrive files on demand). (Anatol) +- Standard: + . Fixed bug #75535 (Inappropriately parsing HTTP response leads to PHP + segment fault). (Nikita) + 23 Nov 2017 PHP 7.0.26 - Core: diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 1822566a21d..e60ac225c90 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -796,6 +796,10 @@ finish: && (*http_header_value == ' ' || *http_header_value == '\t')) { http_header_value++; } + } else { + /* There is no colon. Set the value to the end of the header line, which is + * effectively an empty string. */ + http_header_value = e; } if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) { @@ -812,11 +816,11 @@ finish: strlcpy(location, http_header_value, sizeof(location)); } else if (!strncasecmp(http_header_line, "Content-Type:", sizeof("Content-Type:")-1)) { php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_value, 0); - } else if (!strncasecmp(http_header_line, "Content-Length:", sizeof("Content-Length")-1)) { + } else if (!strncasecmp(http_header_line, "Content-Length:", sizeof("Content-Length:")-1)) { file_size = atoi(http_header_value); php_stream_notify_file_size(context, file_size, http_header_line, 0); } else if ( - !strncasecmp(http_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding")-1) + !strncasecmp(http_header_line, "Transfer-Encoding:", sizeof("Transfer-Encoding:")-1) && !strncasecmp(http_header_value, "Chunked", sizeof("Chunked")-1) ) { diff --git a/ext/standard/tests/http/bug75535.phpt b/ext/standard/tests/http/bug75535.phpt new file mode 100644 index 00000000000..9bf298cc065 --- /dev/null +++ b/ext/standard/tests/http/bug75535.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #75535: Inappropriately parsing HTTP response leads to PHP segment fault +--SKIPIF-- + +--INI-- +allow_url_fopen=1 +--FILE-- + +==DONE== +--EXPECT-- +string(0) "" +array(2) { + [0]=> + string(15) "HTTP/1.0 200 Ok" + [1]=> + string(14) "Content-Length" +} +==DONE==