Skip to content

Crash in zend_objects_store_free_object_storage due to uninitialised handlers #11734

Closed
@tstarling

Description

@tstarling

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:

  1. 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.
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions