Bug #66040 [Com]: Cloning an object while having reference to members results incorrect clone

From: Date: Mon, 04 Jun 2018 17:49:55 +0000
Subject: Bug #66040 [Com]: Cloning an object while having reference to members results incorrect clone
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-215487@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=66040&edit=1 ID: 66040 Comment by: david at frankieandshadow dot com Reported by: bawolff+wn at gmail dot com Summary: Cloning an object while having reference to members results incorrect clone Status: Open Type: Bug Package: Scripting Engine problem Operating System: linux PHP Version: 5.5Git-2013-11-07 (snap) Block user comment: N Private report: N New Comment: I think I am encountering this bug, in a slightly different arrangement, and in PHP7.0.27 (the most up-to-date Debian release of PHP), so if it is the same, as seems likely, it's a rather nasty core bug that's been around for a long time. I also verified that @bawolff's example still fails in 7.0.27. I have while ($q->f($obj) > 0) { $list[$obj->field] = clone $obj; } where f sets fields in $obj. The list ends up with all 'field' members being the same as the final one. I don't think there is any PHP I could write in f that would do this accidentally as it doesn't have access to $list and clone should make the objects be distinct from each other. If I change it to: while ($q->f($obj) > 0) { $k = obj->field; $list[$k] = clone $obj; } it works. Whether this is because the code generated has been perturbed slightly, or it really is changing the example enough to not be hitting the bug I can't tell. But my guess is the while code block is equivalent to @bawolff's function and the $list[$k] is the reference that is still live when it calls f again causing it to overwrite - which is why I think my bug is essentially the same. This isn't the case for all f. In my case f is the result of a database query defined by $q, and f results in a MySQL select, returning the number of results remaining. I simplified it down to mimicking that returning objects in turn from a short array instead, but that doesn't fail. Previous Comments: ------------------------------------------------------------------------ [2013-11-07 02:54:13] bawolff+wn at gmail dot com Description: ------------ The problem is easiest understood by looking at the test script. Basically, if you clone an object in a function that as one of its arguments (or one of its calling functions) has a reference to a member variable of this object, the clone of the object is not correct for the field that the reference is to. The fields of the two objects behave as if they are references to each other (To clarify I do not mean fields point to the same object as is expected, I mean the field itself is a reference to the other field.). If you assign something to that member variable, the change is reflected in both the cloned object and the original, where it should only be reflected in the object that the assignment was for. Tested on snapshot php5.5-201311070030 Also tested on earlier versions like 5.3.3-7 Originally discovered while investigating a bug in MediaWiki: https://bugzilla.wikimedia.org/show_bug.cgi?id=56226 Test script: --------------- <?php $originalObj = new A; class A { var $foo = 'default value'; } // Important note: If you remove the &, the bug disappears. function changeFooWithUnusedReference( &$unusedReferenceToFoo, $newValue ) { global $originalObj; $newObj = clone $originalObj; echo $originalObj->foo . "\n"; echo $newObj->foo . "\n"; $newObj->foo = $newValue; echo $originalObj->foo . "\n"; echo $newObj->foo . "\n"; } changeFooWithUnusedReference( $originalObj->foo, 'Some other value' ); Expected result: ---------------- I expect the following output: default value default value default value Some other value Actual result: -------------- Following output: default value default value Some other value Some other value ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=66040&edit=1

« previous php.bugs (#215487) next »