File tree Expand file tree Collapse file tree 5 files changed +55
-2
lines changed Expand file tree Collapse file tree 5 files changed +55
-2
lines changed Original file line number Diff line number Diff line change @@ -49,6 +49,9 @@ PHP NEWS
4949- Reflection:
5050 . Fixed bug GH-16601 (Memory leak in Reflection constructors). (nielsdos)
5151
52+ - Session:
53+ . Fixed bug GH-16590 (UAF in session_encode()). (nielsdos)
54+
5255- SPL:
5356 . Fixed bug GH-16588 (UAF in Observer->serialize). (nielsdos)
5457 . Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed
Original file line number Diff line number Diff line change @@ -391,6 +391,8 @@ PHP 8.4 INTERNALS UPGRADE NOTES
391391 needing to create a zend_string.
392392 - The ext/session/php_session.h doesn't transitively include the
393393 ext/hash/php_hash.h header anymore.
394+ - It is no longer allowed to return out of the PS_ENCODE_LOOP macro.
395+ Instead, you should break out of the loop instead.
394396
395397 i. ext/xml
396398 - Made the expat compatibility wrapper XML_GetCurrentByteIndex return a long
Original file line number Diff line number Diff 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
308314PHPAPI ZEND_EXTERN_MODULE_GLOBALS (ps )
Original file line number Diff line number Diff line change @@ -1056,6 +1056,7 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
10561056{
10571057 smart_str buf = {0 };
10581058 php_serialize_data_t var_hash ;
1059+ bool fail = false;
10591060 PS_ENCODE_VARS ;
10601061
10611062 PHP_VAR_SERIALIZE_INIT (var_hash );
@@ -1065,12 +1066,17 @@ PS_SERIALIZER_ENCODE_FUNC(php) /* {{{ */
10651066 if (memchr (ZSTR_VAL (key ), PS_DELIMITER , ZSTR_LEN (key ))) {
10661067 PHP_VAR_SERIALIZE_DESTROY (var_hash );
10671068 smart_str_free (& buf );
1068- return NULL ;
1069+ fail = true;
1070+ break ;
10691071 }
10701072 smart_str_appendc (& buf , PS_DELIMITER );
10711073 php_var_serialize (& buf , struc , & var_hash );
10721074 );
10731075
1076+ if (fail ) {
1077+ return NULL ;
1078+ }
1079+
10741080 smart_str_0 (& buf );
10751081
10761082 PHP_VAR_SERIALIZE_DESTROY (var_hash );
Original file line number Diff line number Diff line change 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:{}"
You can’t perform that action at this time.
0 commit comments