]> granicus.if.org Git - php/commitdiff
Simplify __clone() visibility check (magic methods still don't respect ZEND_ACC_CHANGED).
authorDmitry Stogov <dmitry@zend.com>
Thu, 13 Sep 2018 10:36:09 +0000 (13:36 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 13 Sep 2018 10:36:09 +0000 (13:36 +0300)
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index fa2f17571de145a1160840a98fc53a1ec20a35a9..6859654bbe77061cbce0e76b5bf6d3484677cf9a 100644 (file)
@@ -2287,6 +2287,10 @@ static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DAT
        }
 }
 
+static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_clone_call(zend_function *clone, zend_class_entry *scope)
+{
+       zend_throw_error(NULL, "Call to %s %s::__clone() from context '%s'", zend_visibility_string(clone->common.fn_flags), ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+}
 
 #if ZEND_INTENSIVE_DEBUGGING
 
index e51589a40a1b220da6124250a401c1bc52e9575e..0b7ebf8f8999145af764bff7b623b99fa32c10ed 100644 (file)
@@ -5029,23 +5029,12 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
                HANDLE_EXCEPTION();
        }
 
-       if (clone) {
-               if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
-                       /* Ensure that if we're calling a private function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (!zend_check_private(clone, scope, clone->common.function_name)) {
-                               zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
-                               FREE_OP1();
-                               ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               HANDLE_EXCEPTION();
-                       }
-               } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
-                       /* Ensure that if we're calling a protected function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
-                               zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+       if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+               scope = EX(func)->op_array.scope;
+               if (clone->common.scope != scope) {
+                       if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+                        || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+                               zend_wrong_clone_call(clone, scope);
                                FREE_OP1();
                                ZVAL_UNDEF(EX_VAR(opline->result.var));
                                HANDLE_EXCEPTION();
index d3a937de975f3510eda342c7bec88487f824be10..ecde1bcddc3920bc01aac9b432fe88f3a0292ef7 100644 (file)
@@ -3048,23 +3048,12 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_
                HANDLE_EXCEPTION();
        }
 
-       if (clone) {
-               if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
-                       /* Ensure that if we're calling a private function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (!zend_check_private(clone, scope, clone->common.function_name)) {
-                               zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
-
-                               ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               HANDLE_EXCEPTION();
-                       }
-               } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
-                       /* Ensure that if we're calling a protected function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
-                               zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+       if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+               scope = EX(func)->op_array.scope;
+               if (clone->common.scope != scope) {
+                       if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+                        || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+                               zend_wrong_clone_call(clone, scope);
 
                                ZVAL_UNDEF(EX_VAR(opline->result.var));
                                HANDLE_EXCEPTION();
@@ -12588,23 +12577,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
                HANDLE_EXCEPTION();
        }
 
-       if (clone) {
-               if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
-                       /* Ensure that if we're calling a private function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (!zend_check_private(clone, scope, clone->common.function_name)) {
-                               zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
-                               zval_ptr_dtor_nogc(free_op1);
-                               ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               HANDLE_EXCEPTION();
-                       }
-               } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
-                       /* Ensure that if we're calling a protected function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
-                               zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+       if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+               scope = EX(func)->op_array.scope;
+               if (clone->common.scope != scope) {
+                       if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+                        || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+                               zend_wrong_clone_call(clone, scope);
                                zval_ptr_dtor_nogc(free_op1);
                                ZVAL_UNDEF(EX_VAR(opline->result.var));
                                HANDLE_EXCEPTION();
@@ -30665,23 +30643,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
                HANDLE_EXCEPTION();
        }
 
-       if (clone) {
-               if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
-                       /* Ensure that if we're calling a private function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (!zend_check_private(clone, scope, clone->common.function_name)) {
-                               zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
-
-                               ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               HANDLE_EXCEPTION();
-                       }
-               } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
-                       /* Ensure that if we're calling a protected function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
-                               zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+       if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+               scope = EX(func)->op_array.scope;
+               if (clone->common.scope != scope) {
+                       if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+                        || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+                               zend_wrong_clone_call(clone, scope);
 
                                ZVAL_UNDEF(EX_VAR(opline->result.var));
                                HANDLE_EXCEPTION();
@@ -37428,23 +37395,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
                HANDLE_EXCEPTION();
        }
 
-       if (clone) {
-               if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
-                       /* Ensure that if we're calling a private function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (!zend_check_private(clone, scope, clone->common.function_name)) {
-                               zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
-
-                               ZVAL_UNDEF(EX_VAR(opline->result.var));
-                               HANDLE_EXCEPTION();
-                       }
-               } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
-                       /* Ensure that if we're calling a protected function, we're allowed to do so.
-                        */
-                       scope = EX(func)->op_array.scope;
-                       if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
-                               zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+       if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+               scope = EX(func)->op_array.scope;
+               if (clone->common.scope != scope) {
+                       if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+                        || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+                               zend_wrong_clone_call(clone, scope);
 
                                ZVAL_UNDEF(EX_VAR(opline->result.var));
                                HANDLE_EXCEPTION();