]> granicus.if.org Git - php/commitdiff
Fix GMP unserialization with self-reference
authorNikita Popov <nikic@php.net>
Mon, 25 Jul 2016 21:02:54 +0000 (23:02 +0200)
committerNikita Popov <nikic@php.net>
Mon, 25 Jul 2016 21:04:00 +0000 (23:04 +0200)
ext/gmp/gmp.c
ext/gmp/tests/unserialize_with_reference.phpt [new file with mode: 0644]

index a1e15899c99422098f8274cf3f474b8097281d11..b84ede63ff0fed478fdc6fee2c18137f7376b6f1 100644 (file)
@@ -588,10 +588,15 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch
        zval *zv;
        int retval = FAILURE;
        php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data;
+       zval object_copy;
 
        PHP_VAR_UNSERIALIZE_INIT(unserialize_data);
        gmp_create(object, &gmpnum);
 
+       /* The "object" variable may be modified during the execution of this unserialize handler
+        * (it may turn into a reference). Keep the original object around for futher operations. */
+       ZVAL_COPY_VALUE(&object_copy, object);
+
        p = buf;
        max = buf + buf_len;
 
@@ -614,7 +619,7 @@ static int gmp_unserialize(zval *object, zend_class_entry *ce, const unsigned ch
 
        if (zend_hash_num_elements(Z_ARRVAL_P(zv)) != 0) {
                zend_hash_copy(
-                       zend_std_get_properties(object), Z_ARRVAL_P(zv),
+                       zend_std_get_properties(&object_copy), Z_ARRVAL_P(zv),
                        (copy_ctor_func_t) zval_add_ref
                );
        }
diff --git a/ext/gmp/tests/unserialize_with_reference.phpt b/ext/gmp/tests/unserialize_with_reference.phpt
new file mode 100644 (file)
index 0000000..b733430
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Unserialize GMP instance with internal reference to itself
+--FILE--
+<?php
+$s = 'C:3:"GMP":23:{s:1:"2";a:1:{i:46;R:1;}}';
+var_dump(unserialize($s));
+?>
+--EXPECT--
+object(GMP)#1 (2) {
+  [46]=>
+  *RECURSION*
+  ["num"]=>
+  string(1) "2"
+}