From f4128389f47c567373a44924f70036d5badfcd4e Mon Sep 17 00:00:00 2001 From: Florian MARGAINE Date: Sat, 27 Sep 2014 23:40:11 +0200 Subject: [PATCH] Fixes setcookie to only send one Set-Cookie header per name According to the IETF RFC 6265, only one Set-Cookie header should be sent per cookie name. Fixes #67736 --- ext/standard/basic_functions.c | 7 +++ ext/standard/head.c | 6 +++ .../network/bug67736-display-errors-off.phpt | 48 +++++++++++++++++++ .../network/bug67736-display-errors-on.phpt | 33 +++++++++++++ ext/standard/tests/network/setcookie.phpt | 44 ++++++++--------- main/SAPI.h | 1 + 6 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 ext/standard/tests/network/bug67736-display-errors-off.phpt create mode 100644 ext/standard/tests/network/bug67736-display-errors-on.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index ca14b28ccd22b..4b47c870f44b4 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3747,6 +3747,9 @@ PHP_RINIT_FUNCTION(basic) /* {{{ */ /* Default to global filters only */ FG(stream_filters) = NULL; + ALLOC_HASHTABLE(SG(set_cookies)); + zend_hash_init(SG(set_cookies), 0, NULL, NULL, 0); + return SUCCESS; } /* }}} */ @@ -3803,6 +3806,10 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */ BG(page_uid) = -1; BG(page_gid) = -1; + + zend_hash_destroy(SG(set_cookies)); + FREE_HASHTABLE(SG(set_cookies)); + return SUCCESS; } /* }}} */ diff --git a/ext/standard/head.c b/ext/standard/head.c index eca032a97b1fb..228fe152823d7 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -91,6 +91,12 @@ PHPAPI int php_setcookie(char *name, int name_len, char *value, int value_len, t return FAILURE; } + if (zend_hash_exists(SG(set_cookies), name, name_len + 1) == 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "should not be used twice with the same name"); + } else { + zend_hash_add_empty_element(SG(set_cookies), name, name_len + 1); + } + len += name_len; if (value && url_encode) { int encoded_value_len; diff --git a/ext/standard/tests/network/bug67736-display-errors-off.phpt b/ext/standard/tests/network/bug67736-display-errors-off.phpt new file mode 100644 index 0000000000000..0529116de3f95 --- /dev/null +++ b/ext/standard/tests/network/bug67736-display-errors-off.phpt @@ -0,0 +1,48 @@ +--TEST-- +setcookie() emits 2 cookies with same name with display_error off +--DESCRIPTION-- +--INI-- +display_errors=0 +--FILE-- + $header) { + if ($header !== $expected[$i]) { + $bad++; + echo "Header mismatch:\n\tExpected: " + . $expected[$i] + . "\n\tReceived: " + . $header + . "\n"; + } +} + +echo ($bad === 0) + ? 'OK' + : 'A total of ' . $bad . ' errors found.'; +--EXPECTHEADERS-- + +--EXPECT-- +OK \ No newline at end of file diff --git a/ext/standard/tests/network/bug67736-display-errors-on.phpt b/ext/standard/tests/network/bug67736-display-errors-on.phpt new file mode 100644 index 0000000000000..094967041d3e1 --- /dev/null +++ b/ext/standard/tests/network/bug67736-display-errors-on.phpt @@ -0,0 +1,33 @@ +--TEST-- +setcookie() emits 1 cookie then adds a warning for 2nd with same name +--DESCRIPTION-- +--INI-- +--FILE-- +