1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix regression with header removal removing whole prefixes (#21020)

* Fix regression with header removing removing whole prefixes

The header removal code looked for the colon for key-value at the wrong
place, so it would overzealously remove headers. Tweak that condition,
and make the alternative condition only active if it's set (with the
remove prefix op case).

Fixes GH-21018.

* avoid reading past the actual length

* Rename variable to be more clear
This commit is contained in:
Calvin Buckley
2026-01-28 16:50:06 -04:00
committed by GitHub
parent 00466a068e
commit cd32c597a7
2 changed files with 29 additions and 3 deletions

View File

@@ -0,0 +1,21 @@
--TEST--
GH-21018 (header() removes headers with the same prefix)
--INI--
expose_php=On
--CGI--
--FILE--
<?php
header('a: 1');
header('a-test: 1');
header('a: 1');
var_dump(headers_list());
?>
--EXPECTF--
array(3) {
[0]=>
string(%d) "X-Powered-By: PHP/%s"
[1]=>
string(9) "a-test: 1"
[2]=>
string(4) "a: 1"
}

View File

@@ -601,7 +601,7 @@ static void sapi_update_response_code(int ncode)
* since zend_llist_del_element only removes one matched item once,
* we should remove them manually
*/
static void sapi_remove_header(zend_llist *l, char *name, size_t len, size_t header_len)
static void sapi_remove_header(zend_llist *l, char *name, size_t len, size_t prefix_len)
{
sapi_header_struct *header;
zend_llist_element *next;
@@ -610,8 +610,13 @@ static void sapi_remove_header(zend_llist *l, char *name, size_t len, size_t hea
while (current) {
header = (sapi_header_struct *)(current->data);
next = current->next;
if (header->header_len > header_len
&& (header->header[header_len] == ':' || len > header_len)
/*
* prefix_len is set for DELETE_PREFIX (used for deleting i.e.
* "Set-Cookie: PHPSESSID=", where we need more than just key)
* look for the : otherwise
*/
if (header->header_len > len
&& (header->header[len] == ':' || (prefix_len && len > prefix_len))
&& !strncasecmp(header->header, name, len)) {
if (current->prev) {
current->prev->next = next;