php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52719 array_walk_recursive crashes if third param of the function is by reference
Submitted: 2010-08-27 22:42 UTC Modified: 2012-03-02 18:06 UTC
Votes:6
Avg. Score:4.0 ± 0.8
Reproduced:6 of 6 (100.0%)
Same Version:4 (66.7%)
Same OS:2 (33.3%)
From: apouch at woozworld dot com Assigned: nikic (profile)
Status: Closed Package: Arrays related
PHP Version: 5.3.3 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: apouch at woozworld dot com
New email:
PHP Version: OS:

 

 [2010-08-27 22:42 UTC] apouch at woozworld dot com
Description:
------------
This is something that changed between PHP 5.3.2 and PHP 5.3.3.

array_walk_recursive accepts a 3rd parameter for 'userdata'.
If:
- this parameter is an object AND
- the user-created function used as second parameter to array_walk_recursive defines the third parameter by reference AND
- The array given as first parameter to array_walk_recursive is a multi-dimensional array,
PHP crashes.

Test script:
---------------
$array = array('foo', 'bar' => array('taz'));
$foo = new stdClass();
array_walk_recursive($array, create_function('&$v, $k, &$u', ''), $foo);
echo 'No crash';
//This one works: array_walk_recursive($array, create_function('&$v, $k, $u', ''), $foo);




Expected result:
----------------
No Crash

Actual result:
--------------
PHP crashes

Patches

array_walk_recursive.patch (last revision 2012-01-27 13:06 UTC by nikic@php.net)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-08-30 19:36 UTC] johannes@php.net
-Status: Open +Status: Feedback
 [2010-08-30 19:36 UTC] johannes@php.net
Please try using this snapshot:

  http://snaps.php.net/php5.3-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/

I get no crash but a memleak which is handled gracefully with current SVN.

No crash[Mon Aug 30 19:33:37 2010]  Script:  '-'
/home/johannes/src/php/php-src/branches/PHP_5_3/Zend/zend_execute_API.c(888) :  Freeing 0x00DEB060 (32 bytes), script=-
=== Total 1 memory leaks detected ===
 [2010-12-13 13:19 UTC] php at oxanvanleeuwen dot nl
This is still a problem with PHP 5.3.4. Strange is that it segfaults after the call to array_walk_recursive; running is printed. 

See this test script, which segfaults:
<?php
$array = array("hello", array("bye"));
$flat = array();
array_walk_recursive($array, function (&$value, $key, &$flat) {
  $flat[] = $value;
}, $flat);
echo "Running";
 [2011-12-21 16:16 UTC] nikic@php.net
Another test case: http://codepad.viper-7.com/Mw3DhS. You can observe the memory corruption in the values that are output. Also you can simply toggle the crash be removing the 'alpha' elements: http://codepad.viper-7.com/luVZw5 will crash.

By the way, I could not reproduce the crash on a debug build (I get only leaks there, too).
 [2011-12-23 11:42 UTC] nikita dot ppv at googlemail dot com
This issue was caused by http://svn.php.net/viewvc?view=revision&revision=300371 which was commited as a fix for https://bugs.php.net/bug.php?id=51552.

Basically for a recursive array walk the zval will be zval_ptr_dtor'd prematurely and multiple times (every time it leaves one recursive array_walk call). This leads to the memory corruption and in some cases to a segfault.

I'm not exactly sure what purpose that change served, at least the respective phpt test runs cleanly if I revert the changeset.
 [2012-01-27 13:06 UTC] nikic@php.net
The following patch has been added/updated:

Patch Name: array_walk_recursive.patch
Revision:   1327669602
URL:        https://bugs.php.net/patch-display.php?bug=52719&patch=array_walk_recursive.patch&revision=1327669602
 [2012-01-27 13:10 UTC] nikic@php.net
-Status: Feedback +Status: Re-Opened
 [2012-01-27 13:10 UTC] nikic@php.net
I added a patch that fixes the issue.

Now the function works on the userdata as zval* instead of zval**. This fixes the 
issue because zend_call_func changes the zval** for a by-ref var and thus 
zval_ptr_dtor() is called on a different zval than Z_ADDREF_PP() was called on.
 [2012-03-02 18:05 UTC] nikic@php.net
Automatic comment from SVN on behalf of nikic
Revision: http://svn.php.net/viewvc/?view=revision&amp;revision=323837
Log: Fix bug #52719: array_walk_recursive crashes if third param of the function is by reference
 [2012-03-02 18:06 UTC] nikic@php.net
This bug has been fixed in SVN.

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/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.


 [2012-03-02 18:06 UTC] nikic@php.net
-Status: Re-Opened +Status: Closed -Assigned To: +Assigned To: nikic
 [2012-04-18 09:45 UTC] laruence@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=695b9c6720774f826d890e19b288d61efe9cede8
Log: Fix bug #52719: array_walk_recursive crashes if third param of the function is by reference
 [2012-07-24 23:36 UTC] rasmus@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=695b9c6720774f826d890e19b288d61efe9cede8
Log: Fix bug #52719: array_walk_recursive crashes if third param of the function is by reference
 [2013-11-17 09:33 UTC] laruence@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=695b9c6720774f826d890e19b288d61efe9cede8
Log: Fix bug #52719: array_walk_recursive crashes if third param of the function is by reference
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 11:01:29 2024 UTC