Skip to content

Commit 173bdb2

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-16590: UAF in session_encode() Fix various memory leaks on error conditions in openssl_x509_parse()
2 parents 0ce151b + cc39bc2 commit 173bdb2

File tree

4 files changed

+64
-10
lines changed

4 files changed

+64
-10
lines changed

ext/openssl/openssl.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,15 +2153,15 @@ PHP_FUNCTION(openssl_x509_parse)
21532153
/* Can return NULL on error or memory allocation failure */
21542154
if (!bn_serial) {
21552155
php_openssl_store_errors();
2156-
RETURN_FALSE;
2156+
goto err;
21572157
}
21582158

21592159
hex_serial = BN_bn2hex(bn_serial);
21602160
BN_free(bn_serial);
21612161
/* Can return NULL on error or memory allocation failure */
21622162
if (!hex_serial) {
21632163
php_openssl_store_errors();
2164-
RETURN_FALSE;
2164+
goto err;
21652165
}
21662166

21672167
str_serial = i2s_ASN1_INTEGER(NULL, asn1_serial);
@@ -2233,19 +2233,15 @@ PHP_FUNCTION(openssl_x509_parse)
22332233
bio_out = BIO_new(BIO_s_mem());
22342234
if (bio_out == NULL) {
22352235
php_openssl_store_errors();
2236-
RETURN_FALSE;
2236+
goto err_subitem;
22372237
}
22382238
if (nid == NID_subject_alt_name) {
22392239
if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) {
22402240
BIO_get_mem_ptr(bio_out, &bio_buf);
22412241
add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length);
22422242
} else {
2243-
zend_array_destroy(Z_ARR_P(return_value));
22442243
BIO_free(bio_out);
2245-
if (cert_str) {
2246-
X509_free(cert);
2247-
}
2248-
RETURN_FALSE;
2244+
goto err_subitem;
22492245
}
22502246
}
22512247
else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
@@ -2260,6 +2256,16 @@ PHP_FUNCTION(openssl_x509_parse)
22602256
if (cert_str) {
22612257
X509_free(cert);
22622258
}
2259+
return;
2260+
2261+
err_subitem:
2262+
zval_ptr_dtor(&subitem);
2263+
err:
2264+
zend_array_destroy(Z_ARR_P(return_value));
2265+
if (cert_str) {
2266+
X509_free(cert);
2267+
}
2268+
RETURN_FALSE;
22632269
}
22642270
/* }}} */
22652271

ext/session/php_session.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,13 @@ PHPAPI zend_result php_session_reset_id(void);
291291
zend_ulong num_key; \
292292
zval *struc;
293293

294+
/* Do not use a return statement in `code` because that may leak memory.
295+
* Break out of the loop instead. */
294296
#define PS_ENCODE_LOOP(code) do { \
295-
HashTable *_ht = Z_ARRVAL_P(Z_REFVAL(PS(http_session_vars))); \
297+
zval _zv; \
298+
/* protect against user interference */ \
299+
ZVAL_COPY(&_zv, Z_REFVAL(PS(http_session_vars))); \
300+
HashTable *_ht = Z_ARRVAL(_zv); \
296301
ZEND_HASH_FOREACH_KEY(_ht, num_key, key) { \
297302
if (key == NULL) { \
298303
php_error_docref(NULL, E_WARNING, \
@@ -303,6 +308,7 @@ PHPAPI zend_result php_session_reset_id(void);
303308
code; \
304309
} \
305310
} ZEND_HASH_FOREACH_END(); \
311+
zval_ptr_dtor(&_zv); \
306312
} while(0)
307313

308314
PHPAPI ZEND_EXTERN_MODULE_GLOBALS(ps)

ext/session/session.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
10791079
{
10801080
smart_str buf = {0};
10811081
php_serialize_data_t var_hash;
1082+
bool fail = false;
10821083
PS_ENCODE_VARS;
10831084

10841085
PHP_VAR_SERIALIZE_INIT(var_hash);
@@ -1088,12 +1089,17 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
10881089
if (memchr(ZSTR_VAL(key), PS_DELIMITER, ZSTR_LEN(key))) {
10891090
PHP_VAR_SERIALIZE_DESTROY(var_hash);
10901091
smart_str_free(&buf);
1091-
return NULL;
1092+
fail = true;
1093+
break;
10921094
}
10931095
smart_str_appendc(&buf, PS_DELIMITER);
10941096
php_var_serialize(&buf, struc, &var_hash);
10951097
);
10961098

1099+
if (fail) {
1100+
return NULL;
1101+
}
1102+
10971103
smart_str_0(&buf);
10981104

10991105
PHP_VAR_SERIALIZE_DESTROY(var_hash);

ext/session/tests/gh16590.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-16590 (UAF in session_encode())
3+
--EXTENSIONS--
4+
session
5+
--SKIPIF--
6+
<?php include('skipif.inc'); ?>
7+
--INI--
8+
session.use_cookies=0
9+
session.cache_limiter=
10+
session.serialize_handler=php
11+
session.save_handler=files
12+
--FILE--
13+
<?php
14+
15+
class C {
16+
function __serialize() {
17+
$_SESSION = [];
18+
return [];
19+
}
20+
}
21+
22+
session_start();
23+
24+
$_SESSION['Lz'] = new C;
25+
for ($i = 0; $i < 2; $i++) {
26+
$_SESSION[$i] = $i;
27+
}
28+
29+
var_dump(session_encode());
30+
31+
?>
32+
--EXPECTF--
33+
Warning: session_encode(): Skipping numeric key 0 in %s on line %d
34+
35+
Warning: session_encode(): Skipping numeric key 1 in %s on line %d
36+
string(15) "Lz|O:1:"C":0:{}"

0 commit comments

Comments
 (0)