Bug #67824 [NEW]: Combination of array_map, exceptions, anonymous functions causes corruption

From: Date: Tue, 12 Aug 2014 00:29:54 +0000
Subject: Bug #67824 [NEW]: Combination of array_map, exceptions, anonymous functions causes corruption
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-187085@lists.php.net to get a copy of this message
From: tristan dot veness at gmail dot com Operating system: Any PHP version: 5.5.15 Package: Scripting Engine problem Bug Type: Bug Bug description:Combination of array_map, exceptions, anonymous functions causes corruption Description: ------------ When using array_map with an anonymous function that throws an exception - and then manipulating a copy of the stack trace, the original array passed to array_map becomes corrupted. This is a fairly obscure edge case, but I managed to run into it within the framework I'm currently working with. Apologies for the long code sample, I have had alot of difficulty isolating the issue. Test script: --------------- <?php $some_objects = [ new SomeClass(1), new SomeClass(2), new SomeClass(3), new SomeClass(4), ]; $func = function(SomeClass $x) { $x->some_function(); return $x; }; array_walk($some_objects, $func); var_dump($some_objects); $mangled_result = array_map($func, $some_objects); var_dump($mangled_result); class SomeClass { private $number; public function __construct($number) { $this->number = $number; } public function some_function() { try { throw new Exception(); } catch (Exception $e) { MANGLE_SOMEHOW($e->getTrace()); } } } function MANGLE_SOMEHOW($trace) { foreach ($trace as $i => $frame) { if (isset($frame['args'])) { foreach ($frame['args'] as $arg_index => $arg_value) { // And here I was thinking this was a 'copy'??? $frame['args'][$arg_index] = $arg_value; } } } } ?> Expected result: ---------------- array(4) { [0]=> object(SomeClass)#1 (1) { ["number":"SomeClass":private]=> int(1) } [1]=> object(SomeClass)#2 (1) { ["number":"SomeClass":private]=> int(2) } [2]=> object(SomeClass)#3 (1) { ["number":"SomeClass":private]=> int(3) } [3]=> object(SomeClass)#4 (1) { ["number":"SomeClass":private]=> int(4) } } array(4) { [0]=> object(SomeClass)#1 (1) { ["number":"SomeClass":private]=> int(1) } [1]=> object(SomeClass)#2 (1) { ["number":"SomeClass":private]=> int(2) } [2]=> object(SomeClass)#3 (1) { ["number":"SomeClass":private]=> int(3) } [3]=> object(SomeClass)#4 (1) { ["number":"SomeClass":private]=> int(4) } } Actual result: -------------- array(4) { [0]=> object(SomeClass)#1 (1) { ["number":"SomeClass":private]=> int(1) } [1]=> object(SomeClass)#2 (1) { ["number":"SomeClass":private]=> int(2) } [2]=> object(SomeClass)#3 (1) { ["number":"SomeClass":private]=> int(3) } [3]=> object(SomeClass)#4 (1) { ["number":"SomeClass":private]=> int(4) } } array(3) { [0]=> object(SomeClass)#1 (1) { ["number":"SomeClass":private]=> int(1) } [140627626761080]=> object(SomeClass)#2 (1) { ["number":"SomeClass":private]=> int(2) } [140627626759920]=> object(SomeClass)#2 (1) { ["number":"SomeClass":private]=> int(2) } } -- Edit bug report at https://bugs.php.net/bug.php?id=67824&edit=1 --

« previous php.bugs (#187085) next »