|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
[2014-08-12 01:30 UTC] requinix@php.net
[2016-07-14 11:29 UTC] dmitry@php.net
[2017-01-08 00:48 UTC] nikic@php.net
-Status: Open
+Status: Closed
-Assigned To:
+Assigned To: nikic
[2017-01-08 00:48 UTC] nikic@php.net
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 04:00:01 2025 UTC |
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) } }