From c142cf2a0d421b2a4a2394ad623bcd6bce843266 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Thu, 22 Oct 2026 20:13:23 +0200 Subject: [PATCH] Don't truncate header lengths to 32 bits A Set-Cookie line of 4 GiB or more had its length truncated, so sapi_header_op() did not check the whole line for new lines and NUL bytes. --- NEWS | 3 +++ ext/standard/head.c | 2 +- .../tests/network/setrawcookie_over_4gib.phpt | 18 ++++++++++++++++++ main/SAPI.c | 4 ++-- 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 ext/standard/tests/network/setrawcookie_over_4gib.phpt diff --git a/NEWS b/NEWS index a35e4ce8132c..443902579ad6 100644 --- a/NEWS +++ b/NEWS @@ -109,6 +109,9 @@ PHP NEWS - SAPI: . Fixed infinite loop in sapi_header_op() for headers of 4 GiB or more. (Martin Mirchev) + . Fixed header length truncation to 32 bits, which let setcookie() and + setrawcookie() skip the new line/NUL check for headers of 4 GiB or more. + (Jorg Sowa) - SOAP: . Fixed use of uninitialized func in do_request() on OOM bailout. diff --git a/ext/standard/head.c b/ext/standard/head.c index b3648a5bcf1e..29cd367901f4 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -192,7 +192,7 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e } ctr.line = ZSTR_VAL(buf.s); - ctr.line_len = (uint32_t) ZSTR_LEN(buf.s); + ctr.line_len = ZSTR_LEN(buf.s); result = sapi_header_op(SAPI_HEADER_ADD, &ctr); zend_string_release(buf.s); diff --git a/ext/standard/tests/network/setrawcookie_over_4gib.phpt b/ext/standard/tests/network/setrawcookie_over_4gib.phpt new file mode 100644 index 000000000000..212c1f043245 --- /dev/null +++ b/ext/standard/tests/network/setrawcookie_over_4gib.phpt @@ -0,0 +1,18 @@ +--TEST-- +setrawcookie() checks the whole Set-Cookie line when it is longer than 4 GiB +--SKIPIF-- + +--INI-- +memory_limit=-1 +--FILE-- + +--EXPECTF-- +Warning: Header may not contain NUL bytes in %s on line %d +bool(false) diff --git a/main/SAPI.c b/main/SAPI.c index 4b6b7b0c90e6..7e3b1d590840 100644 --- a/main/SAPI.c +++ b/main/SAPI.c @@ -797,7 +797,7 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) PHP_STRLCPY(newheader, "Content-type: ", newlen, sizeof("Content-type: ")-1); strlcat(newheader, mimetype, newlen); sapi_header.header = newheader; - sapi_header.header_len = (uint32_t)(newlen - 1); + sapi_header.header_len = newlen - 1; efree(header_line); } efree(mimetype); @@ -904,7 +904,7 @@ SAPI_API int sapi_send_headers(void) if (SG(sapi_headers).http_status_line) { http_status_line.header = SG(sapi_headers).http_status_line; - http_status_line.header_len = (uint32_t)strlen(SG(sapi_headers).http_status_line); + http_status_line.header_len = strlen(SG(sapi_headers).http_status_line); } else { http_status_line.header = buf; http_status_line.header_len = slprintf(buf, sizeof(buf), "HTTP/1.0 %d X", SG(sapi_headers).http_response_code);