mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Fix #80849: HTTP Status header truncation
While truncating the contents of a header is okay, we must never omit the trailing CRLF. Closes GH-7238.
This commit is contained in:
parent
a942cf5b02
commit
a054ef2aad
3
NEWS
3
NEWS
@ -5,6 +5,9 @@ PHP NEWS
|
|||||||
- Core:
|
- Core:
|
||||||
. Fixed bug #72595 (php_output_handler_append illegal write access). (cmb)
|
. Fixed bug #72595 (php_output_handler_append illegal write access). (cmb)
|
||||||
|
|
||||||
|
- CGI:
|
||||||
|
. Fixed bug #80849 (HTTP Status header truncation). (cmb)
|
||||||
|
|
||||||
- Standard:
|
- Standard:
|
||||||
. Fixed bug #72146 (Integer overflow on substr_replace). (cmb)
|
. Fixed bug #72146 (Integer overflow on substr_replace). (cmb)
|
||||||
|
|
||||||
|
@ -387,7 +387,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
|||||||
|
|
||||||
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
|
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
|
||||||
char *s;
|
char *s;
|
||||||
len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
|
len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s", SG(sapi_headers).http_status_line);
|
||||||
if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
|
if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
|
||||||
response_status = atoi((s + 1));
|
response_status = atoi((s + 1));
|
||||||
}
|
}
|
||||||
@ -404,7 +404,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
|||||||
(s - SG(sapi_headers).http_status_line) >= 5 &&
|
(s - SG(sapi_headers).http_status_line) >= 5 &&
|
||||||
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
|
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
|
||||||
) {
|
) {
|
||||||
len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
|
len = slprintf(buf, sizeof(buf), "Status:%s", s);
|
||||||
response_status = atoi((s + 1));
|
response_status = atoi((s + 1));
|
||||||
} else {
|
} else {
|
||||||
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||||
@ -427,9 +427,9 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
|||||||
err++;
|
err++;
|
||||||
}
|
}
|
||||||
if (err->str) {
|
if (err->str) {
|
||||||
len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str);
|
len = slprintf(buf, sizeof(buf), "Status: %d %s", SG(sapi_headers).http_response_code, err->str);
|
||||||
} else {
|
} else {
|
||||||
len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
|
len = slprintf(buf, sizeof(buf), "Status: %d", SG(sapi_headers).http_response_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,6 +437,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
|
|||||||
|
|
||||||
if (!has_status) {
|
if (!has_status) {
|
||||||
PHPWRITE_H(buf, len);
|
PHPWRITE_H(buf, len);
|
||||||
|
PHPWRITE_H("\r\n", 2);
|
||||||
ignore_status = 1;
|
ignore_status = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
sapi/cgi/tests/bug80849-cgi.phpt
Normal file
10
sapi/cgi/tests/bug80849-cgi.phpt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
--TEST--
|
||||||
|
Bug #80849 (HTTP Status header truncation)
|
||||||
|
--CGI--
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
header('HTTP/1.1 201 ' . str_repeat('A', 1014), true);
|
||||||
|
?>
|
||||||
|
--EXPECTHEADERS--
|
||||||
|
Status: 201 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
--EXPECT--
|
@ -328,7 +328,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
|
|||||||
|
|
||||||
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
|
if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) {
|
||||||
char *s;
|
char *s;
|
||||||
len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line);
|
len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s", SG(sapi_headers).http_status_line);
|
||||||
if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
|
if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) {
|
||||||
response_status = atoi((s + 1));
|
response_status = atoi((s + 1));
|
||||||
}
|
}
|
||||||
@ -345,7 +345,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
|
|||||||
(s - SG(sapi_headers).http_status_line) >= 5 &&
|
(s - SG(sapi_headers).http_status_line) >= 5 &&
|
||||||
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
|
strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
|
||||||
) {
|
) {
|
||||||
len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s);
|
len = slprintf(buf, sizeof(buf), "Status:%s", s);
|
||||||
response_status = atoi((s + 1));
|
response_status = atoi((s + 1));
|
||||||
} else {
|
} else {
|
||||||
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||||
@ -368,9 +368,9 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
|
|||||||
err++;
|
err++;
|
||||||
}
|
}
|
||||||
if (err->str) {
|
if (err->str) {
|
||||||
len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->str);
|
len = slprintf(buf, sizeof(buf), "Status: %d %s", SG(sapi_headers).http_response_code, err->str);
|
||||||
} else {
|
} else {
|
||||||
len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code);
|
len = slprintf(buf, sizeof(buf), "Status: %d", SG(sapi_headers).http_response_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,6 +378,7 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
|
|||||||
|
|
||||||
if (!has_status) {
|
if (!has_status) {
|
||||||
PHPWRITE_H(buf, len);
|
PHPWRITE_H(buf, len);
|
||||||
|
PHPWRITE_H("\r\n", 2);
|
||||||
ignore_status = 1;
|
ignore_status = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
sapi/fpm/tests/bug80849-fpm.phpt
Normal file
40
sapi/fpm/tests/bug80849-fpm.phpt
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
--TEST--
|
||||||
|
Bug #80849 (HTTP Status header truncation)
|
||||||
|
--SKIPIF--
|
||||||
|
<?php include "skipif.inc"; ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once "tester.inc";
|
||||||
|
|
||||||
|
$cfg = <<<EOT
|
||||||
|
[global]
|
||||||
|
error_log = {{FILE:LOG}}
|
||||||
|
[unconfined]
|
||||||
|
listen = {{ADDR}}
|
||||||
|
pm = dynamic
|
||||||
|
pm.max_children = 5
|
||||||
|
pm.start_servers = 1
|
||||||
|
pm.min_spare_servers = 1
|
||||||
|
pm.max_spare_servers = 3
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$code = <<<EOT
|
||||||
|
<?php
|
||||||
|
header('HTTP/1.1 201 ' . str_repeat('A', 1014), true);
|
||||||
|
EOT;
|
||||||
|
|
||||||
|
$tester = new FPM\Tester($cfg, $code);
|
||||||
|
$tester->start();
|
||||||
|
$tester->expectLogStartNotices();
|
||||||
|
$tester
|
||||||
|
->request()
|
||||||
|
->expectHeader('Status', '201 ' . str_repeat('A', 1011));
|
||||||
|
$tester->terminate();
|
||||||
|
$tester->close();
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
require_once "tester.inc";
|
||||||
|
FPM\Tester::clean();
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
Loading…
Reference in New Issue
Block a user