Skip to content

Commit 4ab9663

Browse files
committed
Fix GH-16137: "Deduplicate" *Forwarded* http headers values.
Those are meant to have 1 or plus values separated by a comma even if the client set them separately.
1 parent f8b925b commit 4ab9663

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

sapi/cli/php_cli_server.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,16 +1678,38 @@ static int php_cli_server_client_read_request_on_fragment(php_http_parser *parse
16781678

16791679
static void php_cli_server_client_save_header(php_cli_server_client *client)
16801680
{
1681+
zval *entry;
16811682
/* Wrap header value in a zval to add is to the HashTable which acts as an array */
16821683
zval tmp;
1683-
ZVAL_STR(&tmp, client->current_header_value);
16841684
/* strip off the colon */
16851685
zend_string *lc_header_name = zend_string_tolower_ex(client->current_header_name, /* persistent */ true);
16861686
GC_MAKE_PERSISTENT_LOCAL(lc_header_name);
16871687

1688-
/* Add the wrapped zend_string to the HashTable */
1689-
zend_hash_add(&client->request.headers, lc_header_name, &tmp);
1690-
zend_hash_add(&client->request.headers_original_case, client->current_header_name, &tmp);
1688+
/**
1689+
* **Forwarded** HTTP family headers can have 1 or more values separated by a comma while still
1690+
* possibly be set separately by the client.
1691+
**/
1692+
if (!strstr(ZSTR_VAL(lc_header_name), "forwarded") ||
1693+
(entry = zend_hash_find(&client->request.headers, lc_header_name)) == NULL) {
1694+
ZVAL_STR(&tmp, client->current_header_value);
1695+
1696+
/* Add the wrapped zend_string to the HashTable */
1697+
zend_hash_add(&client->request.headers, lc_header_name, &tmp);
1698+
zend_hash_add(&client->request.headers_original_case, client->current_header_name, &tmp);
1699+
} else {
1700+
zend_string *curval = Z_STR_P(entry);
1701+
zend_string *newval = zend_string_alloc(ZSTR_LEN(curval) + ZSTR_LEN(client->current_header_value) + 2, /* persistent */true);
1702+
1703+
memcpy(ZSTR_VAL(newval), ZSTR_VAL(curval), ZSTR_LEN(curval));
1704+
memcpy(ZSTR_VAL(newval) + ZSTR_LEN(curval), ",", 1);
1705+
memcpy(ZSTR_VAL(newval) + ZSTR_LEN(curval) + 1, ZSTR_VAL(client->current_header_value), ZSTR_LEN(client->current_header_value) + 1);
1706+
1707+
ZVAL_STR(&tmp, newval);
1708+
1709+
/* Update the wrapped zend_string to the HashTable */
1710+
zend_hash_update(&client->request.headers, lc_header_name, &tmp);
1711+
zend_hash_update(&client->request.headers_original_case, client->current_header_name, &tmp);
1712+
}
16911713

16921714
zend_string_release_ex(lc_header_name, /* persistent */ true);
16931715
zend_string_release_ex(client->current_header_name, /* persistent */ true);

0 commit comments

Comments
 (0)