diff --git a/NEWS b/NEWS index 8bd02dc6d6ac..0a4c2bee6009 100644 --- a/NEWS +++ b/NEWS @@ -137,6 +137,8 @@ PHP NEWS (Nicolas Grekas) . Fixed bug GH-24373 (serialize() called from a destructor during var_hash destruction reuses the outer var_hash). (David Carlier) + . Fixed bug GH-24481 (use-after-free in var_destroy() during unserialize() + re-entrancy). (omaraltamimi1) - Streams: . Fixed bug GH-24508 (HTTP wrapper leaks the dechunk filter when header diff --git a/ext/standard/tests/serialize/gh24481.phpt b/ext/standard/tests/serialize/gh24481.phpt new file mode 100644 index 000000000000..1e7dddc93824 --- /dev/null +++ b/ext/standard/tests/serialize/gh24481.phpt @@ -0,0 +1,35 @@ +--TEST-- +GH-24481 (use-after-free in var_destroy() during unserialize() re-entrancy) +--FILE-- + +--EXPECT-- +int(1020) +int(1017) diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index e5cc1acd758c..7b164bb6ed29 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -316,7 +316,11 @@ PHPAPI void var_destroy(php_unserialize_data_t *var_hashx) } } + /* Do not let a destructor re-enter the unserializer: it would reuse the + * var_hash (and its var_entries chunks) that we are destroying here. */ + BG(serialize_lock)++; i_zval_ptr_dtor(zv); + BG(serialize_lock)--; } next = var_dtor_hash->next; efree_size(var_dtor_hash, sizeof(var_dtor_entries));