diff --git a/ext/standard/tests/serialize/gh12265.phpt b/ext/standard/tests/serialize/gh12265.phpt new file mode 100644 index 0000000000000..5f49a62fee29f --- /dev/null +++ b/ext/standard/tests/serialize/gh12265.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __serialize variation +--FILE-- + new A($this)]; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECT-- +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/tests/serialize/gh12265b.phpt b/ext/standard/tests/serialize/gh12265b.phpt new file mode 100644 index 0000000000000..2b9d80a848cee --- /dev/null +++ b/ext/standard/tests/serialize/gh12265b.phpt @@ -0,0 +1,48 @@ +--TEST-- +GH-12265 (Cloning an object breaks serialization recursion) - __sleep variation +--FILE-- +a = new A($this); + return ['a']; + } +} + +class C { + public B $b; + + public function __construct() { + $this->b = new B; + } +} + +$b = new B(); +$sb = serialize($b); +$stb = serialize(new B); + +printf("serialized original: %s\n", $sb); +printf("serialized temp : %s\n", $stb); + +$c = new C; +$sc = serialize($c); +$stc = serialize(new C); + +printf("serialized original: %s\n", $sc); +printf("serialized temp : %s\n", $stc); + +?> +--EXPECT-- +serialized original: O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized temp : O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:1;}} +serialized original: O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} +serialized temp : O:1:"C":1:{s:1:"b";O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"x";r:2;}}} diff --git a/ext/standard/var.c b/ext/standard/var.c index aab00e52d46dd..860b104260ff1 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -671,7 +671,10 @@ static inline zend_long php_add_var_hash(php_serialize_data_t data, zval *var, b return 0; } else if (!in_rcn_array && Z_REFCOUNT_P(var) == 1 - && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1)) { + && (Z_OBJ_P(var)->properties == NULL || GC_REFCOUNT(Z_OBJ_P(var)->properties) == 1) + /* __serialize and __sleep may arbitrarily increase the refcount */ + && Z_OBJCE_P(var)->__serialize == NULL + && zend_hash_find_known_hash(&Z_OBJCE_P(var)->function_table, ZSTR_KNOWN(ZEND_STR_SLEEP)) == NULL) { return 0; }