|  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79710 Reproducible segfault in error_handler during GC involved an SplFileObject
Submitted: 2020-06-18 07:10 UTC Modified: 2020-06-19 08:35 UTC
From: sam at hellosam dot net Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 7.3Git-2020-06-18 (Git) OS: Ubuntu Linux 20.04 LTS
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
Solve the problem:
28 + 49 = ?
Subscribe to this entry?

 [2020-06-18 07:10 UTC] sam at hellosam dot net
Upon calling flock() on a destructed SplFileObject, which is being destructed eariler in the shutdown process while still accessible in another static object yet to be destructed, it will raise an error as expected and calling error_handler, but then the PHP error handling code would cause segmentation fault in the Zend VM engine.

It is beyond my knowledge to understand why that particular error handling code would cause error. The issue was found in my production system using CakePHP, I adopted a few lines of that in the repro script and could 100% reproduce the problem.


Affected version:
* 7.3 GIT 2020-06-13 (verified on 5621c5f)
* 7.3.19
* 7.2 GIT 2020-06-13 (verified on f5b1c32)
* 7.2.31
* On 7.4 branch - fe8fdfa3 is the last commit that shows the error behavior. e219ec144 fixed it. (This is by bisecting the master branch, I don't understand why though)
* On Ubuntu 18.04 LTS latest php-cli package [1:7.2+60ubuntu1] which is PHP 7.2.24-0ubuntu0.18.04.6

Unaffected version (Does not reproduce on):
* 7.4.7
* 7.4 GIT 2020-06-13
* On Ubuntu 20.04 LTS latest php-cli package [7.4.3-4ubuntu2.2] which is PHP 7.4.3

Except for the ubuntu package, I tested by building from GIT source with the following:
./buildconf && ./configure && make -j 4

Test script:
Repro script:

from GIST Link:

Expected result:
Expecting seeing no segmentation fault.

Actual result:
GDB info with GIT fe8fdfa3 built from source on Ubuntu 20.04:

(gdb) run
Starting program: /home/sam/php-src/sapi/cli/php ../repro.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/".
Handle Error 2, flock(): supplied resource is not a valid stream resource

Program received signal SIGSEGV, Segmentation fault.
zend_mm_alloc_small (bin_num=2, size=24, heap=0x7ffff5800040) at /home/sam/php-src/Zend/zend_alloc.c:1279
1279                    heap->free_slot[bin_num] = p->next_free_slot;

(gdb) backtrace
#0  zend_mm_alloc_small (bin_num=2, size=24, heap=0x7ffff5800040) at /home/sam/php-src/Zend/zend_alloc.c:1279
#1  _emalloc_24 () at /home/sam/php-src/Zend/zend_alloc.c:2447
#2  0x0000555555917a07 in ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER () at /home/sam/php-src/Zend/zend_vm_execute.h:46824
#3  0x000055555593cf8c in execute_ex (ex=0x7ffff5800040) at /home/sam/php-src/Zend/zend_vm_execute.h:60107
#4  0x00005555558b0321 in zend_call_function (fci=<optimized out>, fci_cache=0x7ffff586c140) at /home/sam/php-src/Zend/zend_execute_API.c:801
#5  0x00005555558b0619 in _call_user_function_ex (object=object@entry=0x0, function_name=function_name@entry=0x7fffffffbd50, retval_ptr=retval_ptr@entry=0x7fffffffbd40, param_count=param_count@entry=5,
    params=params@entry=0x7fffffffbdd0, no_separation=no_separation@entry=1) at /home/sam/php-src/Zend/zend_execute_API.c:643
#6  0x000055555565c114 in zend_error (type=type@entry=2, format=format@entry=0x555555f939a0 "%s%s%s(): supplied resource is not a valid %s resource") at /home/sam/php-src/Zend/zend.c:1393
#7  0x00005555558d108a in zend_fetch_resource2 (resource_type_name=resource_type_name@entry=0x555555f7f9f9 "stream", resource_type2=3, resource_type1=<optimized out>, res=<optimized out>) at /home/sam/php-src/Zend/zend_list.c:116
#8  0x00005555558d125d in zend_fetch_resource2 (res=<optimized out>, resource_type_name=resource_type_name@entry=0x555555f7f9f9 "stream", resource_type1=<optimized out>, resource_type2=resource_type2@entry=3)
    at /home/sam/php-src/Zend/zend_list.c:105
#9  0x00005555557fa144 in zif_flock (execute_data=0x7ffff581c0f0, return_value=0x7fffffffc080) at /home/sam/php-src/ext/standard/file.c:349
#10 0x00005555558b021f in zend_call_function (fci=fci@entry=0x7fffffffc0b0, fci_cache=fci_cache@entry=0x7fffffffc090) at /home/sam/php-src/Zend/zend_execute_API.c:815
#11 0x00005555557c675f in spl_filesystem_file_call (intern=<optimized out>, func_ptr=0x5555560ebbf0, pass_num_args=1, arg2=<optimized out>, return_value=<optimized out>, return_value=<optimized out>)
    at /home/sam/php-src/ext/spl/spl_directory.c:2089
#12 0x0000555555945445 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /home/sam/php-src/Zend/zend_vm_execute.h:983
#13 execute_ex (ex=0x7ffff5800040) at /home/sam/php-src/Zend/zend_vm_execute.h:55163
#14 0x00005555558b0321 in zend_call_function (fci=fci@entry=0x7fffffffc2d0, fci_cache=0x7ffff588d160, fci_cache@entry=0x7fffffffc2b0) at /home/sam/php-src/Zend/zend_execute_API.c:801
#15 0x00005555558ee4b2 in zend_objects_destroy_object (object=0x7ffff585f348) at /home/sam/php-src/Zend/zend_objects.c:163
#16 0x00005555558f2ce6 in zend_objects_store_call_destructors (objects=objects@entry=0x5555560cef68 <executor_globals+840>) at /home/sam/php-src/Zend/zend_objects_API.c:55
#17 0x00005555558aeeab in shutdown_destructors () at /home/sam/php-src/Zend/zend_execute_API.c:242
#18 0x00005555558be0e5 in zend_call_destructors () at /home/sam/php-src/Zend/zend.c:1136
#19 0x00005555558603a5 in php_request_shutdown (dummy=<optimized out>) at /home/sam/php-src/main/main.c:1879
#20 0x0000555555947e20 in do_cli (argc=2, argv=0x5555560e5ae0) at /home/sam/php-src/sapi/cli/php_cli.c:1159
#21 0x0000555555675d18 in main (argc=2, argv=0x5555560e5ae0) at /home/sam/php-src/sapi/cli/php_cli.c:1384

(gdb) zbacktrace
[0x7ffff581c220] Hash->merge(array(1)[0x7ffff581c270], array(1)[0x7ffff581c280]) /home/sam/repro.php:13
[0x7ffff581c160] Run->handleError(2, "flock(): supplied resource is not a valid stream resource", , , "/home/sam/repro.php") /home/sam/repro.php:50
[0x7ffff581c0f0] flock(resource(#-176156384), 2) [internal function]
[0x7ffff581c090] SplFileObject->flock(2) [internal function]
[0x7ffff581c020] Target->__destruct() /home/sam/repro.php:27
[0x7fffffffc210] ???


Add a Patch

Pull Requests

Add a Pull Request


AllCommentsChangesGit/SVN commitsRelated reports
 [2020-06-19 07:53 UTC]
-Status: Open +Status: Verified
 [2020-06-19 07:53 UTC]
This also happens on newer versions (7.4, master), it just doesn't crash. There's use-after-free under valgrind.
 [2020-06-19 08:35 UTC]
Smaller reproducer for valgrind:

class Target
    public $sfo;
    public function __construct($sfo) {
        $this->sfo = $sfo;
    public function __destruct() {
        // If the SplFileObject is destructed first,
        // underlying FD is no longer valid and will cause error upon calling flock

class Run
    static $sfo;
    static $foo;
    public static function main() {
        // Creation ordering is important for repro
        // $sfo needed to be destructed before $foo.
        Run::$sfo = new SplTempFileObject();
        Run::$foo = new Target(Run::$sfo);


First error:

==187903== Invalid read of size 4
==187903==    at 0xA02EBF: zend_gc_addref (zend_types.h:991)
==187903==    by 0xA0622B: zend_call_function (zend_execute_API.c:737)
==187903==    by 0x7BE28E: spl_filesystem_file_call (spl_directory.c:2096)
==187903==    by 0x7C02EF: zim_spl_SplFileObject_flock (spl_directory.c:2726)
==187903==    by 0xA8940E: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:984)
==187903==    by 0xAF723F: execute_ex (zend_vm_execute.h:55527)
==187903==    by 0xA06339: zend_call_function (zend_execute_API.c:756)
==187903==    by 0xA6DFF8: zend_objects_destroy_object (zend_objects.c:159)
==187903==    by 0xA74AA9: zend_objects_store_call_destructors (zend_objects_API.c:57)
==187903==    by 0xA043CA: shutdown_destructors (zend_execute_API.c:242)
==187903==    by 0xA1CFC0: zend_call_destructors (zend.c:1089)
==187903==    by 0x980AE6: php_request_shutdown (main.c:1875)
==187903==  Address 0x9632490 is 0 bytes inside a block of size 24 free'd
==187903==    at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/
==187903==    by 0x9E52C6: _efree (zend_alloc.c:2516)
==187903==    by 0xA3A21A: list_entry_destructor (zend_list.c:187)
==187903==    by 0xA34B24: _zend_hash_del_el_ex (zend_hash.c:1182)
==187903==    by 0xA3544C: zend_hash_index_del (zend_hash.c:1381)
==187903==    by 0xA39C99: zend_list_delete (zend_list.c:48)
==187903==    by 0x9A1889: _php_stream_free (streams.c:448)
==187903==    by 0x7B7E8B: spl_filesystem_object_destroy_object (spl_directory.c:94)
==187903==    by 0xA74AA9: zend_objects_store_call_destructors (zend_objects_API.c:57)
==187903==    by 0xA043CA: shutdown_destructors (zend_execute_API.c:242)
==187903==    by 0xA1CFC0: zend_call_destructors (zend.c:1089)
==187903==    by 0x980AE6: php_request_shutdown (main.c:1875)
==187903==  Block was alloc'd at
==187903==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/
==187903==    by 0x9E5FF1: __zend_malloc (zend_alloc.c:2909)
==187903==    by 0x9E5215: _emalloc (zend_alloc.c:2502)
==187903==    by 0xA39BC7: zend_list_insert (zend_list.c:41)
==187903==    by 0xA39E1A: zend_register_resource (zend_list.c:96)
==187903==    by 0x9A1577: _php_stream_alloc (streams.c:310)
==187903==    by 0x9A87EB: _php_stream_temp_create_ex (memory.c:586)
==187903==    by 0x9A88BB: _php_stream_temp_create (memory.c:598)
==187903==    by 0x8B5B95: php_stream_url_wrap_php (php_fopen_wrapper.c:207)
==187903==    by 0x9A5AE3: _php_stream_open_wrapper_ex (streams.c:2046)
==187903==    by 0x7B8722: spl_filesystem_file_open (spl_directory.c:299)
==187903==    by 0x7BEFF5: zim_spl_SplTempFileObject___construct (spl_directory.c:2338)
 [2020-06-19 08:48 UTC]
Automatic comment on behalf of
Log: Fixed bug #79710
 [2020-06-19 08:48 UTC]
-Status: Verified +Status: Closed
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Jun 15 17:01:31 2024 UTC