php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #61115 Stream related segfault on fatal error in php_stream_context_del_link
Submitted: 2012-02-16 21:59 UTC Modified: 2012-05-19 14:58 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: nikic@php.net Assigned: cataphract (profile)
Status: Closed Package: Reproducible crash
PHP Version: 5.4.0RC7 OS:
Private report: No CVE-ID: None
 [2012-02-16 21:59 UTC] nikic@php.net
Description:
------------
<?php

$arrayLarge = array_fill(0, 113663, '*');

$resourceFileTemp = fopen('php://temp', 'wr');
stream_context_set_params($resourceFileTemp, array());
preg_replace('', function () { }, $resourceFileTemp);

The above script produces a segfault. The array_fill line is irrelevant for the 
bug itself, but I needed it to get a segfault on non-debug builds too (without 
it it only segfaulted on debug builds.)

The type of the file resource is irrelevant, it is not restricted to php://temp.

The preg_replace + function() { } only serves the purpose to create a fatal 
error with the file argument, but apart from that should be irrelevant (it also 
occurs in lots of other situations that create a fatal error in a function 
call.)

This segfault basically occurs in situations where:
1. A file resource is opened
2. Some stream operation is performed on it
3. A fatal error is issued from a function which the file resource was passed to

Here is the backtrace:


(gdb) run workingFile5_segfault.php 
Starting program: /usr/local/bin/php workingFile5_segfault.php
[Thread debugging using libthread_db enabled]

Catchable fatal error: Object of class Closure could not be converted to string 
in /home/nikic/dev/my-fuzzer/results/workingFile5_segfault.php on line 8

Program received signal SIGSEGV, Segmentation fault.
0x084c95cb in php_stream_context_del_link (context=0xb73cbddc, 
    stream=0xb73cba00) at /home/nikic/dev/php-src/main/streams/streams.c:2256
2256		for(zend_hash_internal_pointer_reset(Z_ARRVAL_P(context-
>links));
(gdb) bt
#0  0x084c95cb in php_stream_context_del_link (context=0xb73cbddc, 
    stream=0xb73cba00) at /home/nikic/dev/php-src/main/streams/streams.c:2256
#1  0x084c4953 in _php_stream_free (stream=0xb73cba00, close_options=3, 
    tsrm_ls=0x8b26050) at /home/nikic/dev/php-src/main/streams/streams.c:449
#2  0x084c48a4 in _php_stream_free (stream=0xb73cbb90, close_options=11, 
    tsrm_ls=0x8b26050) at /home/nikic/dev/php-src/main/streams/streams.c:406
#3  0x084c7059 in stream_resource_regular_dtor (rsrc=0xb73cbca0, 
    tsrm_ls=0x8b26050) at /home/nikic/dev/php-src/main/streams/streams.c:1578
#4  0x085587f3 in list_entry_destructor (ptr=0xb73cbca0)
    at /home/nikic/dev/php-src/Zend/zend_list.c:183
#5  0x08555fc6 in zend_hash_apply_deleter (ht=0x8b280ac, p=0xb73cbc4c)
    at /home/nikic/dev/php-src/Zend/zend_hash.c:650
#6  0x08556154 in zend_hash_graceful_reverse_destroy (ht=0x8b280ac)
    at /home/nikic/dev/php-src/Zend/zend_hash.c:687
#7  0x085589d5 in zend_destroy_rsrc_list (ht=0x8b280ac, tsrm_ls=0x8b26050)
    at /home/nikic/dev/php-src/Zend/zend_list.c:239
#8  0x0854474a in zend_deactivate (tsrm_ls=0x8b26050)
    at /home/nikic/dev/php-src/Zend/zend.c:940
#9  0x084a6b4d in php_request_shutdown (dummy=0x0)
    at /home/nikic/dev/php-src/main/main.c:1781
#10 0x086907c5 in do_cli (argc=2, argv=0xbffff3d4, tsrm_ls=0x8b26050)
    at /home/nikic/dev/php-src/sapi/cli/php_cli.c:1169
#11 0x08691058 in main (argc=2, argv=0xbffff3d4)
    at /home/nikic/dev/php-src/sapi/cli/php_cli.c:1356

I was not yet able to understand the source of the segfault; would be nice if 
someone who knows the stream stuff better could give a hand :)


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-02-21 19:33 UTC] cataphract@php.net
-Status: Open +Status: Analyzed
 [2012-02-21 19:33 UTC] cataphract@php.net
I don't think this can be solved without significant changes.

The stream stores a pointer directly to the context structure (and increments the context resource refcount), but on an unorderly shutdown the resources are simply destroyed in inverse order of created. _php_stream_free then makes invalid reads, not just on the place that causes this segfault, but also near the end when it tries to decrease the context refcount.

I think the solution here would be to have the stream store the context resource id instead of the context structure (basically adding one level of indirection). We may be able to this without breaking binary compatibility, and the details of the stream structure are supposedly private (see comment on php_streams.h), but I have no doubt this would be a very problematic change nonetheless.
 [2012-02-22 11:45 UTC] cataphract@php.net
Automatic comment from SVN on behalf of cataphract
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=323425
Log: - Fixed bug #61115 (stream related segfault on fatal error in
  php_stream_context_link).
#run-tests.php is not currently detecting the segfault in the test
#Missing 5.4 merge
 [2012-02-22 11:46 UTC] cataphract@php.net
Commit fix to 5.3 and trunk.

Merge to 5.4 missing.
 [2012-02-22 11:46 UTC] cataphract@php.net
-Status: Analyzed +Status: Closed -Assigned To: +Assigned To: cataphract
 [2012-02-24 22:56 UTC] cataphract@php.net
Automatic comment from SVN on behalf of cataphract
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=323478
Log: - Better fix for #61115.
- Fixed resource leak in stream_socket_client().
 [2012-02-24 23:50 UTC] nikic@php.net
-Status: Closed +Status: Assigned
 [2012-02-24 23:50 UTC] nikic@php.net
Leaving this open until this is merged to 5.4 as per cjones request.
 [2012-03-17 19:37 UTC] cataphract@php.net
Automatic comment from SVN on behalf of cataphract
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=324324
Log: - Fixed bug #61371 (resource leak). This bug had two parts, a long standing leak
  already fixed in trunk/5.3 and now merged onto 5.4 and a leak introduced in
  fixing bug #61115. This better fix for #61115 fixes the leak (the inhibition
  for deleting the context was too broad) and so prevents segfaults in new
  circumstances (where the inhibition was not broad enough).
 [2012-04-18 09:45 UTC] laruence@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e132db7a57a6afc53cceec15f19541ec29d8233a
Log: - Fixed bug #61371 (resource leak). This bug had two parts, a long standing leak   already fixed in trunk/5.3 and now merged onto 5.4 and a leak introduced in   fixing bug #61115. This better fix for #61115 fixes the leak (the inhibition   for deleting the context was too broad) and so prevents segfaults in new   circumstances (where the inhibition was not broad enough).
 [2012-04-18 09:46 UTC] laruence@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cde766222616500155c204e12bc24036b63eb82e
Log: - Fixed bug #61115 (stream related segfault on fatal error in   php_stream_context_link). #run-tests.php is not currently detecting the segfault in the test #Missing 5.4 merge
 [2012-05-19 14:58 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2012-05-19 14:58 UTC] nikic@php.net
Forgot to close this.
 [2012-07-24 23:36 UTC] rasmus@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e132db7a57a6afc53cceec15f19541ec29d8233a
Log: - Fixed bug #61371 (resource leak). This bug had two parts, a long standing leak   already fixed in trunk/5.3 and now merged onto 5.4 and a leak introduced in   fixing bug #61115. This better fix for #61115 fixes the leak (the inhibition   for deleting the context was too broad) and so prevents segfaults in new   circumstances (where the inhibition was not broad enough).
 [2012-07-24 23:37 UTC] rasmus@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cde766222616500155c204e12bc24036b63eb82e
Log: - Fixed bug #61115 (stream related segfault on fatal error in   php_stream_context_link). #run-tests.php is not currently detecting the segfault in the test #Missing 5.4 merge
 [2013-11-17 09:33 UTC] laruence@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=e132db7a57a6afc53cceec15f19541ec29d8233a
Log: - Fixed bug #61371 (resource leak). This bug had two parts, a long standing leak   already fixed in trunk/5.3 and now merged onto 5.4 and a leak introduced in   fixing bug #61115. This better fix for #61115 fixes the leak (the inhibition   for deleting the context was too broad) and so prevents segfaults in new   circumstances (where the inhibition was not broad enough).
 [2013-11-17 09:33 UTC] laruence@php.net
Automatic comment on behalf of cataphract
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cde766222616500155c204e12bc24036b63eb82e
Log: - Fixed bug #61115 (stream related segfault on fatal error in   php_stream_context_link). #run-tests.php is not currently detecting the segfault in the test #Missing 5.4 merge
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 08:01:29 2024 UTC