diff options
| -rw-r--r-- | ext/standard/tests/serialize/counting_of_references.phpt | 14 | ||||
| -rw-r--r-- | ext/standard/var.c | 10 |
2 files changed, 22 insertions, 2 deletions
diff --git a/ext/standard/tests/serialize/counting_of_references.phpt b/ext/standard/tests/serialize/counting_of_references.phpt new file mode 100644 index 0000000000..e7ead96759 --- /dev/null +++ b/ext/standard/tests/serialize/counting_of_references.phpt @@ -0,0 +1,14 @@ +--TEST-- +References are not counted twice +--FILE-- +<?php + +$ref1 = 1; +$ref2 = 2; + +$arr = [&$ref1, &$ref1, &$ref2, &$ref2]; +var_dump(serialize($arr)); + +?> +--EXPECT-- +string(38) "a:4:{i:0;i:1;i:1;R:2;i:2;i:2;i:3;R:3;}" diff --git a/ext/standard/var.c b/ext/standard/var.c index 194715edf0..53fd54c647 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -604,15 +604,16 @@ static inline uint32_t php_add_var_hash(php_serialize_data_t data, zval *var TSR { zval *zv; zend_ulong key; + zend_bool is_ref = Z_ISREF_P(var); data->n += 1; - if (Z_TYPE_P(var) != IS_OBJECT && Z_TYPE_P(var) != IS_REFERENCE) { + if (!is_ref && Z_TYPE_P(var) != IS_OBJECT) { return 0; } /* References to objects are treated as if the reference didn't exist */ - if (Z_TYPE_P(var) == IS_REFERENCE && Z_TYPE_P(Z_REFVAL_P(var)) == IS_OBJECT) { + if (is_ref && Z_TYPE_P(Z_REFVAL_P(var)) == IS_OBJECT) { var = Z_REFVAL_P(var); } @@ -622,6 +623,11 @@ static inline uint32_t php_add_var_hash(php_serialize_data_t data, zval *var TSR zv = zend_hash_index_find(&data->ht, key); if (zv) { + /* References are only counted once, undo the data->n increment above */ + if (is_ref) { + data->n -= 1; + } + return Z_LVAL_P(zv); } else { zval zv_n; |
