Skip to content

Commit 4d5c5b3

Browse files
committed
Try to convert all parameters to appropriate type
Currently leaking on ext/session/tests/session_set_cookie_params_error.phpt
1 parent c5c26c7 commit 4d5c5b3

File tree

5 files changed

+67
-33
lines changed

5 files changed

+67
-33
lines changed

ext/session/session.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,11 +1671,12 @@ PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t
16711671
Set session cookie parameters */
16721672
static PHP_FUNCTION(session_set_cookie_params)
16731673
{
1674-
zval *lifetime_or_options, *lifetime = NULL;
1675-
zend_string *path = NULL, *domain = NULL, *samesite = NULL;
1676-
zend_bool secure, secure_null = 1;
1677-
zend_bool httponly, httponly_null = 1;
1674+
zval *lifetime_or_options;
1675+
zend_string *lifetime = NULL, *path = NULL, *domain = NULL, *samesite = NULL;
1676+
zend_bool secure = 0, secure_null = 1;
1677+
zend_bool httponly = 0, httponly_null = 1;
16781678
zend_string *ini_name;
1679+
int found = 0;
16791680

16801681
if (!PS(use_cookies)) {
16811682
return;
@@ -1701,22 +1702,20 @@ static PHP_FUNCTION(session_set_cookie_params)
17011702
}
17021703

17031704
if (Z_TYPE_P(lifetime_or_options) == IS_ARRAY) {
1704-
int found = 0;
17051705
zend_string *key;
17061706
zval *value;
17071707

17081708
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(lifetime_or_options), key, value) {
17091709
if (key) {
17101710
ZVAL_DEREF(value);
17111711
if(!strcasecmp("lifetime", ZSTR_VAL(key))) {
1712-
lifetime = value;
1713-
convert_to_string_ex(lifetime);
1712+
lifetime = zval_get_string(value);
17141713
found++;
17151714
} else if(!strcasecmp("path", ZSTR_VAL(key))) {
1716-
path = Z_STR_P(value);
1715+
path = zval_get_string(value);
17171716
found++;
17181717
} else if(!strcasecmp("domain", ZSTR_VAL(key))) {
1719-
domain = Z_STR_P(value);
1718+
domain = zval_get_string(value);
17201719
found++;
17211720
} else if(!strcasecmp("secure", ZSTR_VAL(key))) {
17221721
secure = zval_is_true(value);
@@ -1727,27 +1726,32 @@ static PHP_FUNCTION(session_set_cookie_params)
17271726
httponly_null = 0;
17281727
found++;
17291728
} else if(!strcasecmp("samesite", ZSTR_VAL(key))) {
1730-
samesite = Z_STR_P(value);
1729+
samesite = zval_get_string(value);
17311730
found++;
1731+
} else {
1732+
php_error_docref(NULL, E_WARNING, "Unrecognized key '%s' found in the options array", ZSTR_VAL(key));
17321733
}
1734+
} else {
1735+
php_error_docref(NULL, E_ERROR, "The options array must only use string keys");
1736+
RETURN_FALSE;
17331737
}
17341738
} ZEND_HASH_FOREACH_END();
17351739

17361740
if (found == 0) {
1737-
php_error_docref(NULL, E_WARNING, "No valid options were found in the given array");
1741+
php_error_docref(NULL, E_WARNING, "No valid keys were found in the options array");
17381742
RETURN_FALSE;
17391743
}
17401744
} else {
1741-
lifetime = lifetime_or_options;
1742-
convert_to_string_ex(lifetime);
1745+
lifetime = zval_get_string(lifetime_or_options);
17431746
}
17441747

17451748
if (lifetime) {
17461749
ini_name = zend_string_init("session.cookie_lifetime", sizeof("session.cookie_lifetime") - 1, 0);
1747-
if (zend_alter_ini_entry(ini_name, Z_STR_P(lifetime), PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
1750+
if (zend_alter_ini_entry(ini_name, lifetime, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
17481751
zend_string_release_ex(ini_name, 0);
17491752
RETURN_FALSE;
17501753
}
1754+
zend_string_release(lifetime);
17511755
zend_string_release_ex(ini_name, 0);
17521756
}
17531757
if (path) {
@@ -1756,6 +1760,9 @@ static PHP_FUNCTION(session_set_cookie_params)
17561760
zend_string_release_ex(ini_name, 0);
17571761
RETURN_FALSE;
17581762
}
1763+
if (found > 0) {
1764+
zend_string_release(path);
1765+
}
17591766
zend_string_release_ex(ini_name, 0);
17601767
}
17611768
if (domain) {
@@ -1764,6 +1771,9 @@ static PHP_FUNCTION(session_set_cookie_params)
17641771
zend_string_release_ex(ini_name, 0);
17651772
RETURN_FALSE;
17661773
}
1774+
if (found > 0) {
1775+
zend_string_release(domain);
1776+
}
17671777
zend_string_release_ex(ini_name, 0);
17681778
}
17691779
if (!secure_null) {
@@ -1784,8 +1794,14 @@ static PHP_FUNCTION(session_set_cookie_params)
17841794
}
17851795
if (samesite) {
17861796
ini_name = zend_string_init("session.cookie_samesite", sizeof("session.cookie_samesite") - 1, 0);
1787-
zend_alter_ini_entry(ini_name, samesite, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
1788-
zend_string_release(ini_name);
1797+
if (zend_alter_ini_entry(ini_name, samesite, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == FAILURE) {
1798+
zend_string_release_ex(ini_name, 0);
1799+
RETURN_FALSE;
1800+
}
1801+
if (found > 0) {
1802+
zend_string_release(samesite);
1803+
}
1804+
zend_string_release_ex(ini_name, 0);
17891805
}
17901806

17911807
RETURN_TRUE;

ext/session/tests/session_set_cookie_params_variation7.phpt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@ ob_end_flush();
4242
--EXPECTF--
4343
*** Testing session_set_cookie_params() : array parameter variation ***
4444

45-
Warning: session_set_cookie_params(): No valid options were found in %s
45+
Warning: session_set_cookie_params(): No valid keys were found in the options array in %s
4646
bool(false)
4747

48-
Warning: session_set_cookie_params(): No valid options were found in %s
48+
Warning: session_set_cookie_params(): Unrecognized key 'unknown_key' found in the options array in %s
49+
50+
Warning: session_set_cookie_params(): No valid keys were found in the options array in %s
4951
bool(false)
5052
string(1) "0"
5153
string(0) ""

ext/standard/head.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ PHPAPI int php_header(void)
8080
}
8181
}
8282

83-
PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int url_encode, int httponly, zend_string *samesite)
83+
PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int httponly, zend_string *samesite, int url_encode)
8484
{
8585
char *cookie;
8686
size_t len = sizeof("Set-Cookie: ");
@@ -207,7 +207,7 @@ PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires,
207207
return result;
208208
}
209209

210-
static void php_head_parse_cookie_options_array(zval *options, zend_long *expires, zend_string **path, zend_string **domain, zend_bool *secure, zend_bool *httponly, zend_string **samesite) {
210+
static int php_head_parse_cookie_options_array(zval *options, zend_long *expires, zend_string **path, zend_string **domain, zend_bool *secure, zend_bool *httponly, zend_string **samesite) {
211211
int found = 0;
212212
zend_string *key;
213213
zval *value;
@@ -216,13 +216,13 @@ static void php_head_parse_cookie_options_array(zval *options, zend_long *expire
216216
if (key) {
217217
ZVAL_DEREF(value);
218218
if(!strcasecmp("expire", ZSTR_VAL(key))) {
219-
*expires = Z_LVAL_P(value);
219+
*expires = zval_get_long(value);
220220
found++;
221221
} else if(!strcasecmp("path", ZSTR_VAL(key))) {
222-
*path = Z_STR_P(value);
222+
*path = zval_get_string(value);
223223
found++;
224224
} else if(!strcasecmp("domain", ZSTR_VAL(key))) {
225-
*domain = Z_STR_P(value);
225+
*domain = zval_get_string(value);
226226
found++;
227227
} else if(!strcasecmp("secure", ZSTR_VAL(key))) {
228228
*secure = zval_is_true(value);
@@ -231,19 +231,27 @@ static void php_head_parse_cookie_options_array(zval *options, zend_long *expire
231231
*httponly = zval_is_true(value);
232232
found++;
233233
} else if(!strcasecmp("samesite", ZSTR_VAL(key))) {
234-
*samesite = Z_STR_P(value);
234+
*samesite = zval_get_string(value);
235235
found++;
236+
} else {
237+
php_error_docref(NULL, E_WARNING, "Unrecognized key '%s' found in the options array", ZSTR_VAL(key));
236238
}
239+
} else {
240+
php_error_docref(NULL, E_ERROR, "The options array must only use string keys");
241+
return 0;
237242
}
238243
} ZEND_HASH_FOREACH_END();
239244

240245
/* Array is not empty but no valid keys were found */
241-
if (found == 0 && Z_ARRVAL_P(options)->nNumUsed > 0) {
246+
if (found == 0 && zend_hash_num_elements(Z_ARRVAL_P(options)) > 0) {
242247
php_error_docref(NULL, E_WARNING, "No valid options were found in the given array");
248+
return 0;
243249
}
250+
251+
return 1;
244252
}
245253

246-
/* {{{ proto bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
254+
/* {{{ proto bool setcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
247255
setcookie(string name [, string value [, array options]])
248256
Send a cookie */
249257
PHP_FUNCTION(setcookie)
@@ -266,21 +274,23 @@ PHP_FUNCTION(setcookie)
266274

267275
if (expires_or_options) {
268276
if (Z_TYPE_P(expires_or_options) == IS_ARRAY) {
269-
php_head_parse_cookie_options_array(expires_or_options, &expires, &path, &domain, &secure, &httponly, &samesite);
277+
if(!php_head_parse_cookie_options_array(expires_or_options, &expires, &path, &domain, &secure, &httponly, &samesite)) {
278+
RETURN_FALSE;
279+
}
270280
} else {
271281
expires = Z_LVAL_P(expires_or_options);
272282
}
273283
}
274284

275-
if (php_setcookie(name, value, expires, path, domain, secure, 1, httponly, samesite) == SUCCESS) {
285+
if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 1) == SUCCESS) {
276286
RETVAL_TRUE;
277287
} else {
278288
RETVAL_FALSE;
279289
}
280290
}
281291
/* }}} */
282292

283-
/* {{{ proto bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly[, string samesite]]]]]]])
293+
/* {{{ proto bool setrawcookie(string name [, string value [, int expires [, string path [, string domain [, bool secure[, bool httponly]]]]]])
284294
setrawcookie(string name [, string value [, array options]])
285295
Send a cookie with no url encoding of the value */
286296
PHP_FUNCTION(setrawcookie)
@@ -303,13 +313,15 @@ PHP_FUNCTION(setrawcookie)
303313

304314
if (expires_or_options) {
305315
if (Z_TYPE_P(expires_or_options) == IS_ARRAY) {
306-
php_head_parse_cookie_options_array(expires_or_options, &expires, &path, &domain, &secure, &httponly, &samesite);
316+
if(!php_head_parse_cookie_options_array(expires_or_options, &expires, &path, &domain, &secure, &httponly, &samesite)) {
317+
RETURN_FALSE;
318+
}
307319
} else {
308320
expires = Z_LVAL_P(expires_or_options);
309321
}
310322
}
311323

312-
if (php_setcookie(name, value, expires, path, domain, secure, 0, httponly, samesite) == SUCCESS) {
324+
if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, 0) == SUCCESS) {
313325
RETVAL_TRUE;
314326
} else {
315327
RETVAL_FALSE;

ext/standard/head.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ PHP_FUNCTION(headers_list);
3939
PHP_FUNCTION(http_response_code);
4040

4141
PHPAPI int php_header(void);
42-
PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int url_encode, int httponly, zend_string *samesite);
42+
PHPAPI int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int httponly, zend_string *samesite, int url_encode);
4343

4444
#endif

ext/standard/tests/network/setcookie.phpt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ setcookie('name', 'value', 0, '', 'domain.tld');
1717
setcookie('name', 'value', 0, '', '', TRUE);
1818
setcookie('name', 'value', 0, '', '', FALSE, TRUE);
1919

20+
setcookie('name', 'value', ['expire' => $tsp]);
21+
setcookie('name', 'value', ['expire' => $tsn, 'path' => '/path/', 'domain' => 'domain.tld', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict']);
2022

2123
$expected = array(
2224
'Set-Cookie: name=deleted; expires='.date('D, d-M-Y H:i:s', 1).' GMT; Max-Age=0',
@@ -30,7 +32,9 @@ $expected = array(
3032
'Set-Cookie: name=value; path=/path/',
3133
'Set-Cookie: name=value; domain=domain.tld',
3234
'Set-Cookie: name=value; secure',
33-
'Set-Cookie: name=value; HttpOnly'
35+
'Set-Cookie: name=value; HttpOnly',
36+
'Set-Cookie: name=value; expires='.date('D, d-M-Y H:i:s', $tsp).' GMT; Max-Age=5',
37+
'Set-Cookie: name=value; expires='.date('D, d-M-Y H:i:s', $tsn).' GMT; Max-Age=0; path=/path/; domain=domain.tld; secure; HttpOnly; SameSite=Strict'
3438
);
3539

3640
$headers = headers_list();

0 commit comments

Comments
 (0)