diff options
-rw-r--r-- | ext/gmp/gmp.c | 7 | ||||
-rw-r--r-- | ext/gmp/tests/unserialize_with_reference.phpt | 14 |
2 files changed, 20 insertions, 1 deletions
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index b751725e3f..30693da5cb 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -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 index 0000000000..b733430a38 --- /dev/null +++ b/ext/gmp/tests/unserialize_with_reference.phpt @@ -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" +} |