]> granicus.if.org Git - php/commitdiff
Improve unserialize()
authorDmitry Stogov <dmitry@zend.com>
Wed, 12 Dec 2018 17:04:36 +0000 (20:04 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 12 Dec 2018 17:04:36 +0000 (20:04 +0300)
ext/standard/var.c
ext/standard/var_unserializer.re

index f6b6bcf47fb2c4f6cd3452a91f5451405c221f32..108bafca8bb4cf5111a3cb9078b7858a73f55712 100644 (file)
@@ -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) {
index 1b398560918729191dc02edd3b2652c92468bb04..17f330815c02b472db6c9b4ffb7c40b8da682f83 100644 (file)
@@ -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) != '}') {