summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2014-09-24 11:58:13 +0200
committerNikita Popov <nikic@php.net>2014-09-24 12:06:19 +0200
commit75860fa8e1d8ce0c9fd2b505bf7663a4936a7a39 (patch)
tree9b4e10cca902d23a4981a2ee56d1b7ed410ecb69
parentc45924b954e297ada0bb9b4582235922be0a106f (diff)
downloadphp-git-75860fa8e1d8ce0c9fd2b505bf7663a4936a7a39.tar.gz
Fix counting of "R:" references in serialize()
-rw-r--r--ext/standard/tests/serialize/counting_of_references.phpt14
-rw-r--r--ext/standard/var.c10
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;