From 71f430cf067aa7c7ecc4a813df7d6cad19bf8148 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 12 Dec 2018 20:04:36 +0300 Subject: Improve unserialize() --- ext/standard/var.c | 14 ++++++++++++-- ext/standard/var_unserializer.re | 16 ++++++++++------ 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'ext/standard') diff --git a/ext/standard/var.c b/ext/standard/var.c index f6b6bcf47f..108bafca8b 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -1102,15 +1102,25 @@ PHP_FUNCTION(unserialize) php_var_unserialize_set_allowed_classes(var_hash, class_hash); } - retval = var_tmp_var(&var_hash); + if (BG(unserialize).level > 1) { + retval = var_tmp_var(&var_hash); + } else { + retval = return_value; + } if (!php_var_unserialize(retval, &p, p + buf_len, &var_hash)) { if (!EG(exception)) { php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes", (zend_long)((char*)p - buf), buf_len); } + if (BG(unserialize).level <= 1) { + zval_ptr_dtor(return_value); + } RETVAL_FALSE; - } else { + } else if (BG(unserialize).level > 1) { ZVAL_COPY(return_value, retval); + } else if (Z_REFCOUNTED_P(return_value)) { + zend_refcounted *ref = Z_COUNTED_P(return_value); + gc_check_possible_root(ref); } if (class_hash) { diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 1b39856091..17f330815c 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -109,11 +109,13 @@ static inline void var_push(php_unserialize_data_t *var_hashx, zval *rval) PHPAPI void var_push_dtor(php_unserialize_data_t *var_hashx, zval *rval) { - zval *tmp_var = var_tmp_var(var_hashx); - if (!tmp_var) { - return; - } - ZVAL_COPY(tmp_var, rval); + if (Z_REFCOUNTED_P(rval)) { + zval *tmp_var = var_tmp_var(var_hashx); + if (!tmp_var) { + return; + } + ZVAL_COPY(tmp_var, rval); + } } PHPAPI zval *var_tmp_var(php_unserialize_data_t *var_hashx) @@ -510,7 +512,9 @@ string_key: return 0; } - var_push_dtor(var_hash, data); + if (BG(unserialize).level > 1) { + var_push_dtor(var_hash, data); + } zval_ptr_dtor_str(&key); if (elements && *(*p-1) != ';' && *(*p-1) != '}') { -- cgit v1.2.1