php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76302 Segmentation fault due to memory corruption
Submitted: 2018-05-05 17:44 UTC Modified: -
From: volodymyr at wildwolf dot name Assigned:
Status: Open Package: Reproducible crash
PHP Version: 7.1.17 OS: Ubuntu 17.04 x64
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-05-05 17:44 UTC] volodymyr at wildwolf dot name
Description:
------------
Affected PHP versions: 7.0.30 (+ probably earlier version), 7.1.11-7.1.17 (maybe earlier versions); 7.2.x is NOT affected.

PHP is run with USE_ZEND_ALLOC=0

Valgrind log: https://gist.github.com/sjinks/c8d676d7aaf5c0e8db55755cef4e1865/raw/9faad4962b2f327d9efc820cfe4d6de20b50728d/valgrind.log

This seems to be related to resource handling: if `new Body()` is passed anything other than a resource handle, the crash does not happen.

In offsetGet(), if either `$this->raw[$id] = $raw;` or `$this->values[$id] = $raw($this);` (instead, $raw($this) is saved to a local var and that var is returned) is removed, the crash does not happen.


Test script:
---------------
https://gist.github.com/sjinks/c8d676d7aaf5c0e8db55755cef4e1865

Expected result:
----------------
(empty output)

Actual result:
--------------
Segmentation fault (core dumped)

==12639== Invalid read of size 4
==12639==    at 0xA2EB30: gc_mark_grey (zend_gc.c:517)
==12639==    by 0xA2EEF2: gc_mark_roots (zend_gc.c:598)
==12639==    by 0xA30A25: zend_gc_collect_cycles (zend_gc.c:1072)
==12639==    by 0x9D30C8: shutdown_executor (zend_execute_API.c:358)
==12639==    by 0x9F0CC9: zend_deactivate (zend.c:1005)
==12639==    by 0x928227: php_request_shutdown (main.c:1902)
==12639==    by 0xAF2031: do_cli (php_cli.c:1160)
==12639==    by 0xAF29EE: main (php_cli.c:1381)
==12639==  Address 0x10c38d70 is 0 bytes inside a block of size 24 free'd
==12639==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12639==    by 0x9AD66C: _efree (zend_alloc.c:2444)
==12639==    by 0xA0E72D: list_entry_destructor (zend_list.c:189)
==12639==    by 0xA0A026: _zend_hash_del_el_ex (zend_hash.c:997)
==12639==    by 0xA0A81A: zend_hash_index_del (zend_hash.c:1198)
==12639==    by 0xA0E1A6: zend_list_delete (zend_list.c:50)
==12639==    by 0x94E383: _php_stream_free (streams.c:449)
==12639==    by 0x94E2CA: _php_stream_free (streams.c:410)
==12639==    by 0x951232: stream_resource_regular_dtor (streams.c:1619)
==12639==    by 0xA0E2AB: zend_resource_dtor (zend_list.c:76)
==12639==    by 0xA0E8CA: zend_close_rsrc (zend_list.c:230)
==12639==    by 0xA0B9CE: zend_hash_reverse_apply (zend_hash.c:1598)
==12639==    by 0xA0E8F0: zend_close_rsrc_list (zend_list.c:238)
==12639==    by 0x9D300F: shutdown_executor (zend_execute_API.c:353)
==12639==    by 0x9F0CC9: zend_deactivate (zend.c:1005)
==12639==    by 0x928227: php_request_shutdown (main.c:1902)
==12639==    by 0xAF2031: do_cli (php_cli.c:1160)
==12639==    by 0xAF29EE: main (php_cli.c:1381)
==12639==  Block was alloc'd at
==12639==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12639==    by 0x9AE745: __zend_malloc (zend_alloc.c:2838)
==12639==    by 0x9AD4F1: _emalloc (zend_alloc.c:2429)
==12639==    by 0xA0E06C: zend_list_insert (zend_list.c:43)
==12639==    by 0xA0E341: zend_register_resource (zend_list.c:98)
==12639==    by 0x94E042: _php_stream_alloc (streams.c:310)
==12639==    by 0x955726: _php_stream_temp_create_ex (memory.c:579)
==12639==    by 0x9557F2: _php_stream_temp_create (memory.c:591)
==12639==    by 0x80D195: php_stream_url_wrap_php (php_fopen_wrapper.c:211)
==12639==    by 0x952C5F: _php_stream_open_wrapper_ex (streams.c:2055)
==12639==    by 0x7AAF7A: php_if_fopen (file.c:870)
==12639==    by 0x67008C: phar_fopen (func_interceptors.c:427)
==12639==    by 0xA621A4: ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:675)
==12639==    by 0xA614CB: execute_ex (zend_vm_execute.h:429)
==12639==    by 0x9D58E2: zend_call_function (zend_execute_API.c:855)
==12639==    by 0xA200AD: zend_call_method (zend_interfaces.c:99)
==12639==    by 0xA4B2B8: zend_std_read_dimension (zend_object_handlers.c:819)
==12639==    by 0xA5E2FC: zend_fetch_dimension_address_read (zend_execute.c:1873)
==12639==    by 0xA5E59C: zend_fetch_dimension_address_read_R_slow (zend_execute.c:1902)
==12639==    by 0xABA743: ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER (zend_vm_execute.h:38121)
==12639==    by 0xA614CB: execute_ex (zend_vm_execute.h:429)
==12639==    by 0xA616CC: zend_execute (zend_vm_execute.h:474)
==12639==    by 0x9F2C53: zend_execute_scripts (zend.c:1482)
==12639==    by 0x929E6A: php_execute_script (main.c:2577)
==12639==    by 0xAF1541: do_cli (php_cli.c:993)
==12639==    by 0xAF29EE: main (php_cli.c:1381)
==12639== 
==12639== Invalid write of size 4
==12639==    at 0xA2EB39: gc_mark_grey (zend_gc.c:517)
==12639==    by 0xA2EEF2: gc_mark_roots (zend_gc.c:598)
==12639==    by 0xA30A25: zend_gc_collect_cycles (zend_gc.c:1072)
==12639==    by 0x9D30C8: shutdown_executor (zend_execute_API.c:358)
==12639==    by 0x9F0CC9: zend_deactivate (zend.c:1005)
==12639==    by 0x928227: php_request_shutdown (main.c:1902)
==12639==    by 0xAF2031: do_cli (php_cli.c:1160)
==12639==    by 0xAF29EE: main (php_cli.c:1381)
==12639==  Address 0x10c38d70 is 0 bytes inside a block of size 24 free'd
==12639==    at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12639==    by 0x9AD66C: _efree (zend_alloc.c:2444)
==12639==    by 0xA0E72D: list_entry_destructor (zend_list.c:189)
==12639==    by 0xA0A026: _zend_hash_del_el_ex (zend_hash.c:997)
==12639==    by 0xA0A81A: zend_hash_index_del (zend_hash.c:1198)
==12639==    by 0xA0E1A6: zend_list_delete (zend_list.c:50)
==12639==    by 0x94E383: _php_stream_free (streams.c:449)
==12639==    by 0x94E2CA: _php_stream_free (streams.c:410)
==12639==    by 0x951232: stream_resource_regular_dtor (streams.c:1619)
==12639==    by 0xA0E2AB: zend_resource_dtor (zend_list.c:76)
==12639==    by 0xA0E8CA: zend_close_rsrc (zend_list.c:230)
==12639==    by 0xA0B9CE: zend_hash_reverse_apply (zend_hash.c:1598)
==12639==    by 0xA0E8F0: zend_close_rsrc_list (zend_list.c:238)
==12639==    by 0x9D300F: shutdown_executor (zend_execute_API.c:353)
==12639==    by 0x9F0CC9: zend_deactivate (zend.c:1005)
==12639==    by 0x928227: php_request_shutdown (main.c:1902)
==12639==    by 0xAF2031: do_cli (php_cli.c:1160)
==12639==    by 0xAF29EE: main (php_cli.c:1381)
==12639==  Block was alloc'd at
==12639==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==12639==    by 0x9AE745: __zend_malloc (zend_alloc.c:2838)
==12639==    by 0x9AD4F1: _emalloc (zend_alloc.c:2429)
==12639==    by 0xA0E06C: zend_list_insert (zend_list.c:43)
==12639==    by 0xA0E341: zend_register_resource (zend_list.c:98)
==12639==    by 0x94E042: _php_stream_alloc (streams.c:310)
==12639==    by 0x955726: _php_stream_temp_create_ex (memory.c:579)
==12639==    by 0x9557F2: _php_stream_temp_create (memory.c:591)
==12639==    by 0x80D195: php_stream_url_wrap_php (php_fopen_wrapper.c:211)
==12639==    by 0x952C5F: _php_stream_open_wrapper_ex (streams.c:2055)
==12639==    by 0x7AAF7A: php_if_fopen (file.c:870)
==12639==    by 0x67008C: phar_fopen (func_interceptors.c:427)
==12639==    by 0xA621A4: ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:675)
==12639==    by 0xA614CB: execute_ex (zend_vm_execute.h:429)
==12639==    by 0x9D58E2: zend_call_function (zend_execute_API.c:855)
==12639==    by 0xA200AD: zend_call_method (zend_interfaces.c:99)
==12639==    by 0xA4B2B8: zend_std_read_dimension (zend_object_handlers.c:819)
==12639==    by 0xA5E2FC: zend_fetch_dimension_address_read (zend_execute.c:1873)
==12639==    by 0xA5E59C: zend_fetch_dimension_address_read_R_slow (zend_execute.c:1902)
==12639==    by 0xABA743: ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER (zend_vm_execute.h:38121)
==12639==    by 0xA614CB: execute_ex (zend_vm_execute.h:429)
==12639==    by 0xA616CC: zend_execute (zend_vm_execute.h:474)
==12639==    by 0x9F2C53: zend_execute_scripts (zend.c:1482)
==12639==    by 0x929E6A: php_execute_script (main.c:2577)
==12639==    by 0xAF1541: do_cli (php_cli.c:993)
==12639== by 0xAF29EE: main (php_cli.c:1381)
...

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-05-05 17:47 UTC] volodymyr at wildwolf dot name
Could be related to how 'php://temp' is handled:

```
-return new Body(fopen('php://temp', 'r+'));
+return new Body(fopen(__FILE__, 'r+'));
```

and the crash does not happen.
 [2018-05-05 18:15 UTC] volodymyr at wildwolf dot name
The following patch fixes the issue for me:

```
--- 7.1.17/main/streams/streams.c.orig  2018-05-05 21:10:26.585014131 +0300
+++ 7.1.17/main/streams/streams.c       2018-05-05 21:13:42.470900381 +0300
@@ -408,7 +408,7 @@
            * enclosing stream can free this stream. We remove rsrc_dtor because
            * we want the enclosing stream to be deleted from the resource list */
           return php_stream_free(enclosing_stream,
-             (close_options | PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_KEEP_RSRC) & ~PHP_STREAM_FREE_RSRC_DTOR);
+             (close_options | PHP_STREAM_FREE_CALL_DTOR) & ~PHP_STREAM_FREE_RSRC_DTOR);
        }

        /* if we are releasing the stream only (and preserving the underlying handle),
```
 [2018-05-05 18:20 UTC] volodymyr at wildwolf dot name
Sorry, wrong order of files.

```
--- 7.1.17/main/streams/streams.c.orig  2018-05-05 21:13:42.470900381 +0300
+++ 7.1.17/main/streams/streams.c       2018-05-05 21:10:26.585014131 +0300
@@ -408,7 +408,7 @@
                 * enclosing stream can free this stream. We remove rsrc_dtor because
                 * we want the enclosing stream to be deleted from the resource list */
                return php_stream_free(enclosing_stream,
-                       (close_options | PHP_STREAM_FREE_CALL_DTOR) & ~PHP_STREAM_FREE_RSRC_DTOR);
+                       (close_options | PHP_STREAM_FREE_CALL_DTOR | PHP_STREAM_FREE_KEEP_RSRC) & ~PHP_STREAM_FREE_RSRC_DTOR);
        }

        /* if we are releasing the stream only (and preserving the underlying handle),
```

That is, PHP_STREAM_FREE_KEEP_RSRC needs to be added to close_options.
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Nov 16 23:01:41 2019 UTC