Closed
Description
Description
<?php
ini_set('memory_limit', '2M');
$objs = [];
while (true) {
$objs[] = new SplPriorityQueue;
}
This crashes on shutdown:
Program received signal SIGSEGV, Segmentation fault.
0x00005555558e4187 in zend_objects_store_free_object_storage (objects=objects@entry=0x555555ad71a8 <executor_globals+840>, fast_shutdown=fast_shutdown@entry=true) at ./Zend/zend_objects_API.c:107
...
(gdb) print obj->handlers
$2 = (const zend_object_handlers *) 0x0
When an object is created, there is a critical section between zend_object_std_init() and the assignment to handlers during which time it is unsafe to call the Zend allocator.
This was reported in LuaSandbox (T322748) but a quick review suggests that many other extensions have the same issue. In the PHP 8.1 tree, there is:
- dom_nodemap_or_nodelist_objects_new
- pdo_dbh_new
- spl_dllist_object_new_ex
- spl_heap_object_new_ex
- spl_object_storage_new_ex
- spl_array_object_new_ex
- tidy_object_new
- xsl_objects_new
My test case above uses the bug in spl_heap_object_new_ex().
Potential rectification options:
- In zend_objects_store_free_object_storage, guard against !obj->handlers. I think this is a good solution since it should fix the issue in all extensions. obj->handlers is set to NULL in zend_object_alloc(). There are not many ways to access an object when there was a fatal error before a reference was taken. Maybe a guard in zend_objects_store_call_destructors() would also be wise.
- Fix all extensions. Update the comment on zend_object_alloc() to indicate that, in addition to the other requirements, handlers must be set before any allocation is done.
PHP Version
PHP 8.1.20
Operating System
No response