php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #42208 substr_replace() crashes when the same array is passed more than once
Submitted: 2007-08-04 20:13 UTC Modified: 2007-08-05 14:47 UTC
From: gwynne@php.net Assigned:
Status: Closed Package: Reproducible crash
PHP Version: 5CVS-2007-08-04 (CVS) OS: *
Private report: No CVE-ID:
 [2007-08-04 20:13 UTC] gwynne@php.net
Description:
------------
substr_replace( subject, replacement, from, len ) is able to accept arrays for each parameter. However, when any two parameters which are arrays refer to the same array internally, the function can crash due to pointer equality.

For the specific case given, substr_replace() reads a value from $a, performs convert_to_string_ex(), then reads a value from $b and performs convert_to_long_ex(). Because both arrays refer to the same hashtable, the code then ends up with a string expected and a long value instead, and the result is a sometimes-crash.

Reproduce code:
---------------
$a = array( 1, 2 );
$b = array( 1, 2 ); // creates new hashtable
$c = $a; // bumps refcount on $a, no zval_copy_ctor()
var_dump( substr_replace( $a, 1, 1, $b ) );
var_dump( substr_replace( $a, 1, 1, $c ) );

Expected result:
----------------
array(2) {
  [0]=>
  string(2) "11"
  [1]=>
  string(2) "21"
}
array(2) {
  [0]=>
  string(2) "11"
  [1]=>
  string(2) "21"
}


Actual result:
--------------
array(2) {
  [0]=>
  string(2) "11"
  [1]=>
  string(2) "21"
}
Bus error or Segmentation fault

(gdb) bt
#0  0x00290913 in zif_substr_replace (ht=4, return_value=0x17b4728, return_value_ptr=0x0, this_ptr=0x0, return_value_used=1) at /Users/gwynne/src/php-src/php-5cvs/ext/standard/string.c:2341
#1  0x0037c25e in zend_do_fcall_common_helper_SPEC (execute_data=0xbfffd940) at /Users/gwynne/src/php-src/php-5cvs/Zend/zend_vm_execute.h:200
#2  0x003825e3 in ZEND_DO_FCALL_SPEC_CONST_HANDLER (execute_data=0xbfffd940) at /Users/gwynne/src/php-src/php-5cvs/Zend/zend_vm_execute.h:1681
#3  0x0037bd31 in execute (op_array=0x17b360c) at /Users/gwynne/src/php-src/php-5cvs/Zend/zend_vm_execute.h:92
#4  0x00353829 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /Users/gwynne/src/php-src/php-5cvs/Zend/zend.c:1134
#5  0x002f5378 in php_execute_script (primary_file=0xbfffe058) at /Users/gwynne/src/php-src/php-5cvs/main/main.c:1794
#6  0x003d6aab in main (argc=2, argv=0xbfffe17c) at /Users/gwynne/src/php-src/php-5cvs/sapi/cli/php_cli.c:1138


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-08-04 20:15 UTC] gwynne@php.net
Thanks to paul at quakenet dot org for finding the crash.
 [2007-08-05 00:07 UTC] crrodriguez at suse dot de
--TEST--
#42208  substr_replace() crashes when the same array is passed more than once
--FILE--
<?php
$a = array(1, 2);
$c = $a;
var_dump(substr_replace($a, 1, 1, $c ));
?>
--EXPECT--
array(2) {
  [0]=>
  string(2) "11"
  [1]=>
  string(2) "21"
}

Index: ext/standard/string.c
===================================================================
RCS file: /repository/php-src/ext/standard/string.c,v
retrieving revision 1.445.2.14.2.66
diff -u -p -r1.445.2.14.2.66 string.c
--- ext/standard/string.c       30 Jul 2007 14:22:06 -0000      1.445.2.14.2.66
+++ ext/standard/string.c       4 Aug 2007 23:45:28 -0000
@@ -2168,6 +2168,7 @@ PHP_FUNCTION(substr_replace)
        }

        if (argc > 3) {
+               SEPARATE_ZVAL(len);
                if (Z_TYPE_PP(len) != IS_ARRAY) {
                        convert_to_long_ex(len);
                        l = Z_LVAL_PP(len);


(status: works for me ;) )
 [2007-08-05 14:47 UTC] iliaa@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 03:01:55 2014 UTC