]> granicus.if.org Git - php/commitdiff
Revert "Allow internal functions to return values by reference (this was disabled...
authorDmitry Stogov <dmitry@zend.com>
Tue, 17 Oct 2017 10:25:19 +0000 (13:25 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 17 Oct 2017 10:25:19 +0000 (13:25 +0300)
This reverts commit da781a5ac2cb9d2f983ef9fe070900664db12c67.

Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/gmp/tests/unserialize_with_reference.phpt
ext/opcache/Optimizer/zend_func_info.c
ext/standard/basic_functions.c
ext/standard/var.c

index c8194e8f5ba746c9837130cfe3a8245defa05904..b8f0aa1f343d25782d580aa29496aff758ec1659 100644 (file)
@@ -3480,12 +3480,11 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
        fbc->internal_function.handler(call, ret);
 
 #if ZEND_DEBUG
-       if (!EG(exception) && call->func) {
-               ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
-                       zend_verify_internal_return_type(call->func, ret));
-               ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                       !Z_ISREF_P(ret));
-       }
+       ZEND_ASSERT(
+               EG(exception) || !call->func ||
+               !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+               zend_verify_internal_return_type(call->func, ret));
+       ZEND_ASSERT(!Z_ISREF_P(ret));
 #endif
 
        EG(current_execute_data) = execute_data;
@@ -3583,8 +3582,8 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -3677,8 +3676,8 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -7838,12 +7837,10 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
                }
 
 #if ZEND_DEBUG
-               if (!EG(exception) && call->func) {
-                       ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
-                               zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
-               }
+               ZEND_ASSERT(
+                       EG(exception) || !call->func ||
+                       !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+                       zend_verify_internal_return_type(call->func, ret));
 #endif
 
                EG(current_execute_data) = call->prev_execute_data;
index b290c5036e84af65fa1261f33e27791de27cf656..9d99daf98684a731e82eb4df39d8b9b5bc33120a 100644 (file)
@@ -573,12 +573,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV
        fbc->internal_function.handler(call, ret);
 
 #if ZEND_DEBUG
-       if (!EG(exception) && call->func) {
-               ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
-                       zend_verify_internal_return_type(call->func, ret));
-               ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                       !Z_ISREF_P(ret));
-       }
+       ZEND_ASSERT(
+               EG(exception) || !call->func ||
+               !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+               zend_verify_internal_return_type(call->func, ret));
+       ZEND_ASSERT(!Z_ISREF_P(ret));
 #endif
 
        EG(current_execute_data) = execute_data;
@@ -618,12 +617,11 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETV
        fbc->internal_function.handler(call, ret);
 
 #if ZEND_DEBUG
-       if (!EG(exception) && call->func) {
-               ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
-                       zend_verify_internal_return_type(call->func, ret));
-               ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                       !Z_ISREF_P(ret));
-       }
+       ZEND_ASSERT(
+               EG(exception) || !call->func ||
+               !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+               zend_verify_internal_return_type(call->func, ret));
+       ZEND_ASSERT(!Z_ISREF_P(ret));
 #endif
 
        EG(current_execute_data) = execute_data;
@@ -743,8 +741,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -821,8 +819,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_S
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -915,8 +913,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -1040,8 +1038,8 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
                if (!EG(exception) && call->func) {
                        ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
                                zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
+                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
+                               ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
                }
 #endif
 
@@ -2034,12 +2032,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
                }
 
 #if ZEND_DEBUG
-               if (!EG(exception) && call->func) {
-                       ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
-                               zend_verify_internal_return_type(call->func, ret));
-                       ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ||
-                               !Z_ISREF_P(ret));
-               }
+               ZEND_ASSERT(
+                       EG(exception) || !call->func ||
+                       !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
+                       zend_verify_internal_return_type(call->func, ret));
 #endif
 
                EG(current_execute_data) = call->prev_execute_data;
index e1f158070375d7a907bcc207503ec00524835bf4..b733430a3870b07a59be2cbaf13064cea7965de1 100644 (file)
@@ -2,7 +2,7 @@
 Unserialize GMP instance with internal reference to itself
 --FILE--
 <?php
-$s = 'C:3:"GMP":23:{s:1:"2";a:1:{i:46;r:1;}}';
+$s = 'C:3:"GMP":23:{s:1:"2";a:1:{i:46;R:1;}}';
 var_dump(unserialize($s));
 ?>
 --EXPECT--
index 5090363f829083ae44d3536f02440a2b87e4b049..957d53864ec2543ac3b57d0e020ed66410221b7a 100644 (file)
@@ -531,7 +531,7 @@ static const func_info_t func_infos[] = {
        FN("forward_static_call",          UNKNOWN_INFO),
        FN("forward_static_call_array",    UNKNOWN_INFO),
        F1("serialize",                    MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING),
-       FN("unserialize",                  UNKNOWN_INFO | MAY_BE_REF),
+       FN("unserialize",                  UNKNOWN_INFO),
        F0("var_dump",                     MAY_BE_NULL),
        F1("var_export",                   MAY_BE_NULL | MAY_BE_STRING),
        F0("debug_zval_dump",              MAY_BE_NULL),
index 7bb579c692e28d9588e430876710fef5cf73d10b..93d469168b70596e9a839f3298fc9c3794ea0938 100644 (file)
@@ -2669,7 +2669,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_serialize, 0)
        ZEND_ARG_INFO(0, var)
 ZEND_END_ARG_INFO()
 
-ZEND_BEGIN_ARG_INFO_EX(arginfo_unserialize, 0, 1, 1)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_unserialize, 0, 0, 1)
        ZEND_ARG_INFO(0, variable_representation)
        ZEND_ARG_INFO(0, allowed_classes)
 ZEND_END_ARG_INFO()
index f8406d8988b8b7181fca85b4002c3db6a0fe7cfc..e28afe91776fab86ce1c4b65d5329b9169623a79 100644 (file)
@@ -1124,6 +1124,13 @@ PHP_FUNCTION(unserialize)
        /* Reset to previous allowed_classes in case this is a nested call */
        php_var_unserialize_set_allowed_classes(var_hash, prev_class_hash);
        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+
+       /* Per calling convention we must not return a reference here, so unwrap. We're doing this at
+        * the very end, because __wakeup() calls performed during UNSERIALIZE_DESTROY might affect
+        * the value we unwrap here. This is compatible with behavior in PHP <=7.0. */
+       if (Z_ISREF_P(return_value)) {
+               zend_unwrap_reference(return_value);
+       }
 }
 /* }}} */