Skip to content

Commit af324e2

Browse files
committed
Fix issue mentioned in #77302
Apparently Serializable::serialize() can return NULL, which is encoded as N;. As we do not allow back-references to non-object values in PHP 7.3 we need to make sure that any references are also compiled to N;.
1 parent b3e0e55 commit af324e2

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
References to objects for which Serializable::serialize() returned NULL should use N;
3+
--FILE--
4+
<?php
5+
6+
class NotSerializable implements Serializable {
7+
public function serialize() {
8+
return null;
9+
}
10+
11+
public function unserialize($serialized) {
12+
}
13+
}
14+
15+
$obj = new NotSerializable();
16+
$data = [$obj, $obj];
17+
var_dump($s = serialize($data));
18+
var_dump(unserialize($s));
19+
20+
?>
21+
--EXPECT--
22+
string(18) "a:2:{i:0;N;i:1;N;}"
23+
array(2) {
24+
[0]=>
25+
NULL
26+
[1]=>
27+
NULL
28+
}

ext/standard/var.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,11 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
822822
}
823823

824824
if (var_hash && (var_already = php_add_var_hash(var_hash, struc))) {
825-
if (Z_ISREF_P(struc)) {
825+
if (var_already == -1) {
826+
/* Reference to an object that failed to serialize, replace with null. */
827+
smart_str_appendl(buf, "N;", 2);
828+
return;
829+
} else if (Z_ISREF_P(struc)) {
826830
smart_str_appendl(buf, "R:", 2);
827831
smart_str_append_long(buf, var_already);
828832
smart_str_appendc(buf, ';');
@@ -886,6 +890,10 @@ static void php_var_serialize_intern(smart_str *buf, zval *struc, php_serialize_
886890
smart_str_appendl(buf, (char *) serialized_data, serialized_length);
887891
smart_str_appendc(buf, '}');
888892
} else {
893+
/* Mark this value in the var_hash, to avoid creating references to it. */
894+
zval *var_idx = zend_hash_index_find(&var_hash->ht,
895+
(zend_ulong) (zend_uintptr_t) Z_COUNTED_P(struc));
896+
ZVAL_LONG(var_idx, -1);
889897
smart_str_appendl(buf, "N;", 2);
890898
}
891899
if (serialized_data) {

0 commit comments

Comments
 (0)