Skip to content

Commit 71f430c

Browse files
committed
Improve unserialize()
1 parent 8c781c1 commit 71f430c

File tree

2 files changed

+22
-8
lines changed

2 files changed

+22
-8
lines changed

ext/standard/var.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,15 +1102,25 @@ PHP_FUNCTION(unserialize)
11021102
php_var_unserialize_set_allowed_classes(var_hash, class_hash);
11031103
}
11041104

1105-
retval = var_tmp_var(&var_hash);
1105+
if (BG(unserialize).level > 1) {
1106+
retval = var_tmp_var(&var_hash);
1107+
} else {
1108+
retval = return_value;
1109+
}
11061110
if (!php_var_unserialize(retval, &p, p + buf_len, &var_hash)) {
11071111
if (!EG(exception)) {
11081112
php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes",
11091113
(zend_long)((char*)p - buf), buf_len);
11101114
}
1115+
if (BG(unserialize).level <= 1) {
1116+
zval_ptr_dtor(return_value);
1117+
}
11111118
RETVAL_FALSE;
1112-
} else {
1119+
} else if (BG(unserialize).level > 1) {
11131120
ZVAL_COPY(return_value, retval);
1121+
} else if (Z_REFCOUNTED_P(return_value)) {
1122+
zend_refcounted *ref = Z_COUNTED_P(return_value);
1123+
gc_check_possible_root(ref);
11141124
}
11151125

11161126
if (class_hash) {

ext/standard/var_unserializer.re

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval)
109109

110110
PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval)
111111
{
112-
zval *tmp_var = var_tmp_var(var_hashx);
113-
if (!tmp_var) {
114-
return;
115-
}
116-
ZVAL_COPY(tmp_var, rval);
112+
if (Z_REFCOUNTED_P(rval)) {
113+
zval *tmp_var = var_tmp_var(var_hashx);
114+
if (!tmp_var) {
115+
return;
116+
}
117+
ZVAL_COPY(tmp_var, rval);
118+
}
117119
}
118120

119121
PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx)
@@ -510,7 +512,9 @@ string_key:
510512
return 0;
511513
}
512514

513-
var_push_dtor(var_hash, data);
515+
if (BG(unserialize).level > 1) {
516+
var_push_dtor(var_hash, data);
517+
}
514518
zval_ptr_dtor_str(&key);
515519

516520
if (elements && *(*p-1) != ';' && *(*p-1) != '}') {

0 commit comments

Comments
 (0)