From ea2d621e8850b587a7779db54d764568f5849106 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 11 Jun 2025 13:22:02 +0200 Subject: [PATCH 1/5] Fix use after free during shutdown destruction --- Zend/zend_objects_API.c | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 80f5b747db710..c8d3f04d969f6 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -97,33 +97,17 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_ end = objects->object_buckets + 1; obj_ptr = objects->object_buckets + objects->top; - if (fast_shutdown) { - do { - obj_ptr--; - obj = *obj_ptr; - if (IS_OBJ_VALID(obj)) { - if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { - GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); - if (obj->handlers->free_obj != zend_object_std_dtor) { - GC_ADDREF(obj); - obj->handlers->free_obj(obj); - } - } - } - } while (obj_ptr != end); - } else { - do { - obj_ptr--; - obj = *obj_ptr; - if (IS_OBJ_VALID(obj)) { - if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { - GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); - GC_ADDREF(obj); - obj->handlers->free_obj(obj); - } + do { + obj_ptr--; + obj = *obj_ptr; + if (IS_OBJ_VALID(obj)) { + if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); + GC_ADDREF(obj); + obj->handlers->free_obj(obj); } - } while (obj_ptr != end); - } + } + } while (obj_ptr != end); } From 81f808ef4d8b352f3324105149042733cadf963b Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 11 Jun 2025 13:26:37 +0200 Subject: [PATCH 2/5] Bump news --- NEWS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS b/NEWS index 5eb1694b5e816..ed4de1605466c 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ PHP NEWS ?? ??? ????, PHP 8.3.23 - Core: + . Fixed GH-18833 (use after free during destruction). + (Daniil Gentili) . Fixed GH-18695 (zend_ast_export() - float number is not preserved). (Oleg Efimov) From 51357281e5c3b3582178f670508107ebb103e766 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 11 Jun 2025 13:30:38 +0200 Subject: [PATCH 3/5] Add test --- Zend/tests/gh18833.phpt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Zend/tests/gh18833.phpt diff --git a/Zend/tests/gh18833.phpt b/Zend/tests/gh18833.phpt new file mode 100644 index 0000000000000..1c42ccdb596bc --- /dev/null +++ b/Zend/tests/gh18833.phpt @@ -0,0 +1,24 @@ +--TEST-- +Bug #18833 (Use after free with weakmaps dependent on destruction order) +--FILE-- +current(); + +echo "ok\n"; +?> +--EXPECT-- +ok From 7dc3b03f78bae70fc557b4c445bf9af64194eaac Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 16 Jun 2025 11:32:18 +0200 Subject: [PATCH 4/5] Improve fix --- Zend/zend_objects_API.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index c8d3f04d969f6..dd68b43388aab 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -97,17 +97,35 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_ end = objects->object_buckets + 1; obj_ptr = objects->object_buckets + objects->top; - do { - obj_ptr--; - obj = *obj_ptr; - if (IS_OBJ_VALID(obj)) { - if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { - GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); - GC_ADDREF(obj); - obj->handlers->free_obj(obj); + if (fast_shutdown) { + do { + obj_ptr--; + obj = *obj_ptr; + if (IS_OBJ_VALID(obj)) { + if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); + if (obj->handlers->free_obj != zend_object_std_dtor + || OBJ_FLAGS(obj) & IS_OBJ_WEAKLY_REFERENCED + ) { + GC_ADDREF(obj); + obj->handlers->free_obj(obj); + } + } } - } - } while (obj_ptr != end); + } while (obj_ptr != end); + } else { + do { + obj_ptr--; + obj = *obj_ptr; + if (IS_OBJ_VALID(obj)) { + if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { + GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); + GC_ADDREF(obj); + obj->handlers->free_obj(obj); + } + } + } while (obj_ptr != end); + } } From 487f644ad9a1f6827e7fad781036b03a8495ca33 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Mon, 16 Jun 2025 11:37:48 +0200 Subject: [PATCH 5/5] Add parentheses --- Zend/zend_objects_API.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index dd68b43388aab..0844453357773 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -105,7 +105,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_ if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) { GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED); if (obj->handlers->free_obj != zend_object_std_dtor - || OBJ_FLAGS(obj) & IS_OBJ_WEAKLY_REFERENCED + || (OBJ_FLAGS(obj) & IS_OBJ_WEAKLY_REFERENCED) ) { GC_ADDREF(obj); obj->handlers->free_obj(obj);