Bug #69996 [Opn->Csd]: Changing the property of a cloned object affects the original

From: Date: Fri, 10 Jul 2015 08:37:42 +0000
Subject: Bug #69996 [Opn->Csd]: Changing the property of a cloned object affects the original
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-194277@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=69996&edit=1 ID: 69996 Updated by: laruence@php.net Reported by: berdir@php.net Summary: Changing the property of a cloned object affects the original -Status: Open +Status: Closed Type: Bug Package: Scripting Engine problem Operating System: Ubuntu PHP Version: 7.0Git-2015-07-05 (Git) Block user comment: N Private report: N New Comment: Automatic comment on behalf of laruence Revision: http://git.php.net/?p=php-src.git;a=commit;h=f930d6ea0e8ca8723212ab234973d74dbccfc226 Log: Fixed Bug #69996 (Changing the property of a cloned object affects the original) Previous Comments: ------------------------------------------------------------------------ [2015-07-10 08:00:39] laruence@php.net it turns out we can not use fast_copy here: diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 9694cd6..2cc7c6d 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -179,7 +179,9 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o src++; dst++; } while (src != end); - } else if (old_object->properties && !old_object->ce->clone) { + } +#if 0 + else if (old_object->properties && !old_object->ce->clone) { /* fast copy */ if (EXPECTED(old_object->handlers == &std_object_handlers)) { if (EXPECTED(!(GC_FLAGS(old_object->properties) & IS_ARRAY_IMMUTABLE))) { @@ -189,6 +191,7 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o return; } } +#endif if (old_object->properties && EXPECTED(zend_hash_num_elements(old_object->properties))) { thanks ------------------------------------------------------------------------ [2015-07-09 17:59:14] neclimdul at gmail dot com Seems it has to be in a function and it only happens on the 3rd unserialize. Weird characteristics but hopefully that'll help someone debug it. Test case: <?php function method($cache) { $prepared = clone $cache; $prepared->data = unserialize($prepared->data); return $prepared; } $cache = new stdClass(); $cache->data = serialize(['foo' => 'bar']); for ($i = 0; $i < 5; ++$i) { echo "$i\n"; method($cache); } ?> Output: 0 1 2 Warning: unserialize() expects parameter 1 to be string, array given in /.../test2.php on line 5 3 ------------------------------------------------------------------------ [2015-07-05 11:33:09] berdir@php.net Description: ------------ ... under not yet identified descriptions. This is part of our efforts to get Drupal 8 green on PHP 7, see https://www.drupal.org/node/2454439. At some point a very strange bug was introduced in PHP 7, this is a relatively new bug. Many tests have fails, I haven't checked yet if it's the same bug for all of them. You can reproduce by running MemoryBackendUnitTest. https://bugs.php.net/bug.php?id=69371 for example has instructions on how to run a test. The problematic code is in MemoryBackend::prepareItem(): $prepared = clone $cache; $prepared->data = unserialize($prepared->data); This is called repeatedly and on the second call, $cache->data is already unserialized which results in a notice. So it looks like the clone doesn't fully work. $cache is a stdClass object. I tried to extract it into a standalone script but that doesn't fail. When debugging, I noticed that both cloned object have the same hash (spl_object_hash()) and that both $prepared->data and $cache->data are already unserialized. Expected result: ---------------- No error Actual result: -------------- unserialize(): Error at offset 0 of 6 bytes unserialize('foobar') Drupal\Core\Cache\MemoryBackend->prepareItem(Object, 1) Drupal\Core\Cache\MemoryBackend->get('test3', 1) Drupal\system\Tests\Cache\GenericCacheBackendUnitTestBase->testSetGet() Drupal\simpletest\TestBase->run() _simpletest_batch_operation(Array, '7', Array) _batch_process() _batch_do() _batch_page(Object) Drupal\system\Controller\BatchController->batchPage(Object) call_user_func_array(Array, Array) Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) Stack\StackedHttpKernel->handle(Object, 1, 1) Drupal\Core\DrupalKernel->handle(Object) ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=69996&edit=1

« previous php.bugs (#194277) next »