From 896fe8169a9a920fcd8797494ff2a16a4415411d Mon Sep 17 00:00:00 2001 From: Jeff Chan Date: Mon, 17 Feb 2014 03:09:34 +0000 Subject: [PATCH] Fix PMA_arrayWalkRecursive to ensure single pass thru keys Fix a bug with PMA_arrayWalkRecursive that causes it to apply a function to its keys/values more than once. A previously incorrect test is fixed as well. The bug happens because when keys are modified, PHP's foreach loops through the new keys again. This does not usually happen unless the iterating array is passed through by reference (or has refcount=1). See: http://stackoverflow.com/a/14854568/791890 Please see #936 for full explanation. Signed-off-by: Jeff Chan --- libraries/core.lib.php | 8 ++++++++ test/libraries/core/PMA_array_test.php | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libraries/core.lib.php b/libraries/core.lib.php index b21ea2bf22..0614dee5e8 100644 --- a/libraries/core.lib.php +++ b/libraries/core.lib.php @@ -442,11 +442,16 @@ function PMA_arrayMergeRecursive() */ function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false) { + static $walked_keys = array(); static $recursive_counter = 0; if (++$recursive_counter > 1000) { PMA_fatalError(__('possible deep recursion attack')); } foreach ($array as $key => $value) { + if (isset($walked_keys[$key])) { + continue; + } + if (is_array($value)) { PMA_arrayWalkRecursive($array[$key], $function, $apply_to_keys_also); } else { @@ -458,6 +463,9 @@ function PMA_arrayWalkRecursive(&$array, $function, $apply_to_keys_also = false) if ($new_key != $key) { $array[$new_key] = $array[$key]; unset($array[$key]); + $walked_keys[$new_key] = true; + } else { + $walked_keys[$key] = true; } } } diff --git a/test/libraries/core/PMA_array_test.php b/test/libraries/core/PMA_array_test.php index 81a18f423b..86ffcf2c3c 100644 --- a/test/libraries/core/PMA_array_test.php +++ b/test/libraries/core/PMA_array_test.php @@ -369,8 +369,8 @@ class PMA_Array_Test extends PHPUnit_Framework_TestCase 'key3'=>'val3' ); $target = array( - "key1"=>'val1', - 'key2'=>array('skey1'=>'sval1', 'skey2'=>'sval2'), + "key1"=>'v\\al1', + 'key2'=>array('s\\key1'=>'sval1', 'skey2'=>'sval2'), 'key3'=>'val3' );