]> granicus.if.org Git - php/commitdiff
Detect calls to abstract methods in get_method() already
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 5 Sep 2019 08:27:19 +0000 (10:27 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 6 Sep 2019 13:05:24 +0000 (15:05 +0200)
Instead of checking for this during DO_FCALL, already detect this
case during get_method()/get_static_method(), similar to visibility
checks.

This causes a minor difference in behavior, in that arguments will
no longer be evaluated. I think this is correct though (and consistent
with visibility errors).

Zend/zend_execute.c
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
ext/opcache/jit/zend_jit_disasm_x86.c
ext/opcache/jit/zend_jit_internal.h
ext/opcache/jit/zend_jit_vm_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index eec9f6a4791592ba8c994f444439a68ca642f81b..570d5886bdf1aeb7d04201e23d770ea679087305 100644 (file)
@@ -1553,12 +1553,6 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(c
                ZSTR_VAL(fbc->common.function_name));
 }
 
-static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_abstract_method(const zend_function *fbc)
-{
-       zend_throw_error(NULL, "Cannot call abstract method %s::%s()",
-               ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
-}
-
 static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
 {
        zend_uchar c;
index 5621471179b095bf6df2f280094396d1e014423f..3f2dd8a241f2032dbf599c4efd39aec67d6567e4 100644 (file)
@@ -1234,6 +1234,13 @@ static ZEND_COLD zend_never_inline void zend_bad_method_call(zend_function *fbc,
 }
 /* }}} */
 
+static ZEND_COLD zend_never_inline void zend_abstract_method_call(zend_function *fbc) /* {{{ */
+{
+       zend_throw_error(NULL, "Cannot call abstract method %s::%s()",
+               ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+}
+/* }}} */
+
 ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *method_name, const zval *key) /* {{{ */
 {
        zend_object *zobj = *obj_ptr;
@@ -1294,6 +1301,10 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
        }
 
 exit:
+       if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+               zend_abstract_method_call(fbc);
+               fbc = NULL;
+       }
        if (UNEXPECTED(!key)) {
                ZSTR_ALLOCA_FREE(lc_method_name, use_heap);
        }
@@ -1379,6 +1390,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
                }
        }
 
+       if (fbc && UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_ABSTRACT)) {
+               zend_abstract_method_call(fbc);
+               fbc = NULL;
+       }
+
        if (UNEXPECTED(!key)) {
                zend_string_release_ex(lc_function_name, 0);
        }
index f488f803f0b26b20ae14576503ab2733bcff755c..acca3caf4c25a57beb6e3127a9b8b8684f922a80 100644 (file)
@@ -4154,27 +4154,9 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
        zend_execute_data *call = EX(call);
        zend_function *fbc = call->func;
        zval *ret;
-       zval retval;
 
        SAVE_OPLINE();
        EX(call) = call->prev_execute_data;
-       if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
-               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
-                       zend_abstract_method(fbc);
-ZEND_VM_C_LABEL(fcall_except):
-                       UNDEF_RESULT();
-                       if (!RETURN_VALUE_USED(opline)) {
-                               ret = &retval;
-                               ZVAL_UNDEF(ret);
-                       }
-                       ZEND_VM_C_GOTO(fcall_end);
-               } else {
-                       zend_deprecated_function(fbc);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               ZEND_VM_C_GOTO(fcall_except);
-                       }
-               }
-       }
 
        if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
                ret = NULL;
@@ -4197,7 +4179,21 @@ ZEND_VM_C_LABEL(fcall_except):
                        zend_execute_ex(call);
                }
        } else {
+               zval retval;
                ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
+
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+                       zend_deprecated_function(fbc);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               UNDEF_RESULT();
+                               if (!RETURN_VALUE_USED(opline)) {
+                                       ret = &retval;
+                                       ZVAL_UNDEF(ret);
+                               }
+                               ZEND_VM_C_GOTO(fcall_end);
+                       }
+               }
+
                call->prev_execute_data = execute_data;
                EG(current_execute_data) = call;
 
index 1c2c6ab7a3af65591f7b5ec41b8db1cad0fc4947..ca877d4878d53924cda3c073574cfee7da10a5ce 100644 (file)
@@ -1572,27 +1572,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
        zend_execute_data *call = EX(call);
        zend_function *fbc = call->func;
        zval *ret;
-       zval retval;
 
        SAVE_OPLINE();
        EX(call) = call->prev_execute_data;
-       if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
-               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
-                       zend_abstract_method(fbc);
-fcall_except:
-                       UNDEF_RESULT();
-                       if (!0) {
-                               ret = &retval;
-                               ZVAL_UNDEF(ret);
-                       }
-                       goto fcall_end;
-               } else {
-                       zend_deprecated_function(fbc);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               goto fcall_except;
-                       }
-               }
-       }
 
        if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
                ret = NULL;
@@ -1615,7 +1597,21 @@ fcall_except:
                        zend_execute_ex(call);
                }
        } else {
+               zval retval;
                ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
+
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+                       zend_deprecated_function(fbc);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               UNDEF_RESULT();
+                               if (!0) {
+                                       ret = &retval;
+                                       ZVAL_UNDEF(ret);
+                               }
+                               goto fcall_end;
+                       }
+               }
+
                call->prev_execute_data = execute_data;
                EG(current_execute_data) = call;
 
@@ -1677,27 +1673,9 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETV
        zend_execute_data *call = EX(call);
        zend_function *fbc = call->func;
        zval *ret;
-       zval retval;
 
        SAVE_OPLINE();
        EX(call) = call->prev_execute_data;
-       if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
-               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
-                       zend_abstract_method(fbc);
-fcall_except:
-                       UNDEF_RESULT();
-                       if (!1) {
-                               ret = &retval;
-                               ZVAL_UNDEF(ret);
-                       }
-                       goto fcall_end;
-               } else {
-                       zend_deprecated_function(fbc);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               goto fcall_except;
-                       }
-               }
-       }
 
        if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
                ret = NULL;
@@ -1720,7 +1698,21 @@ fcall_except:
                        zend_execute_ex(call);
                }
        } else {
+               zval retval;
                ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
+
+               if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+                       zend_deprecated_function(fbc);
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               UNDEF_RESULT();
+                               if (!1) {
+                                       ret = &retval;
+                                       ZVAL_UNDEF(ret);
+                               }
+                               goto fcall_end;
+                       }
+               }
+
                call->prev_execute_data = execute_data;
                EG(current_execute_data) = call;
 
index 109510cdb216d5d079581c82f31f7b2324c0599c..6bb0c6765c0d80263cc2cdc5e4d432a7c0c70137 100644 (file)
@@ -432,7 +432,7 @@ static int zend_jit_disasm_init(void)
        REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
        REGISTER_HELPER(zend_jit_vm_stack_free_args_helper);
        REGISTER_HELPER(zend_jit_copy_extra_args_helper);
-       REGISTER_HELPER(zend_jit_deprecated_or_abstract_helper);
+       REGISTER_HELPER(zend_jit_deprecated_helper);
        REGISTER_HELPER(zend_jit_assign_const_to_typed_ref);
        REGISTER_HELPER(zend_jit_assign_tmp_to_typed_ref);
        REGISTER_HELPER(zend_jit_assign_var_to_typed_ref);
index bf00b1d1df52b375438c29c7e3d72d810e92f93a..603db0ab4b6dd64f33135f9131696873d719c291 100644 (file)
@@ -88,7 +88,7 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_counter_helper(ZEND_OPCODE_H
 ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_loop_counter_helper(ZEND_OPCODE_HANDLER_ARGS);
 
 void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D);
-void ZEND_FASTCALL zend_jit_deprecated_or_abstract_helper(OPLINE_D);
+void ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D);
 
 void ZEND_FASTCALL zend_jit_get_constant(const zval *key, uint32_t flags);
 int  ZEND_FASTCALL zend_jit_check_constant(const zval *key);
index 332488bc8b677e24b5212b23f3d72755ce0fbb4b..51dbc75828f49fd59dd19eb2d65dbb120d9998a7 100644 (file)
@@ -144,22 +144,14 @@ void ZEND_FASTCALL zend_jit_copy_extra_args_helper(EXECUTE_DATA_D)
        }
 }
 
-void ZEND_FASTCALL zend_jit_deprecated_or_abstract_helper(OPLINE_D)
+void ZEND_FASTCALL zend_jit_deprecated_helper(OPLINE_D)
 {
        zend_execute_data *call = (zend_execute_data *) opline;
        zend_function *fbc = call->func;
-
-       if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
-               zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
-       } else if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
-               zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
-                       fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
-                       fbc->common.scope ? "::" : "",
-                       ZSTR_VAL(fbc->common.function_name));
-       } else {
-               return;
-       }
-
+       zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
+               fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
+               fbc->common.scope ? "::" : "",
+               ZSTR_VAL(fbc->common.function_name));
        if (EG(exception)) {
 #ifndef HAVE_GCC_GLOBAL_REGS
                zend_execute_data *execute_data = EG(current_execute_data);
index 369f91d43a8e7a7c07ca9888cb1902f20b2a7a7f..2473be4198254bfc9451989f931c378caac86ed9 100644 (file)
@@ -7199,31 +7199,25 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
 
        if (opline->opcode == ZEND_DO_FCALL) {
                if (!func) {
-                       |       test dword [r0 + offsetof(zend_op_array, fn_flags)], (ZEND_ACC_DEPRECATED|ZEND_ACC_ABSTRACT)
+                       |       test dword [r0 + offsetof(zend_op_array, fn_flags)], ZEND_ACC_DEPRECATED
                        |       jnz >1
                        |.cold_code
                        |1:
                        if (!GCC_GLOBAL_REGS) {
                                |       mov FCARG1a, RX
                        }
-                       |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
+                       |       EXT_CALL zend_jit_deprecated_helper, r0
                        |       MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
                        |       jne ->exception_handler
                        |       mov r0, EX:RX->func // reload
                        |       jmp >1
                        |.code
                        |1:
-               } else if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
-                       if (!GCC_GLOBAL_REGS) {
-                               |       mov FCARG1a, RX
-                       }
-                       |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
-                       |       jmp ->exception_handler
                } else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
                        if (!GCC_GLOBAL_REGS) {
                                |       mov FCARG1a, RX
                        }
-                       |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
+                       |       EXT_CALL zend_jit_deprecated_helper, r0
                        |       MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
                        |       jne ->exception_handler
                        |       mov r0, EX:RX->func // reload
@@ -7415,31 +7409,25 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, zend_op_ar
                }
                if (opline->opcode == ZEND_DO_FCALL_BY_NAME) {
                        if (!func) {
-                               |       test dword [r0 + offsetof(zend_op_array, fn_flags)], (ZEND_ACC_DEPRECATED|ZEND_ACC_ABSTRACT)
+                               |       test dword [r0 + offsetof(zend_op_array, fn_flags)], ZEND_ACC_DEPRECATED
                                |       jnz >1
                                |.cold_code
                                |1:
                                if (!GCC_GLOBAL_REGS) {
                                        |       mov FCARG1a, RX
                                }
-                               |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
+                               |       EXT_CALL zend_jit_deprecated_helper, r0
                                |       MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
                                |       jne ->exception_handler
                                |       mov r0, EX:RX->func // reload
                                |       jmp >1
                                |.code
                                |1:
-                       } else if (func->common.fn_flags & ZEND_ACC_ABSTRACT) {
-                               if (!GCC_GLOBAL_REGS) {
-                                       |       mov FCARG1a, RX
-                               }
-                               |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
-                               |       jmp ->exception_handler
                        } else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
                                if (!GCC_GLOBAL_REGS) {
                                        |       mov FCARG1a, RX
                                }
-                               |       EXT_CALL zend_jit_deprecated_or_abstract_helper, r0
+                               |       EXT_CALL zend_jit_deprecated_helper, r0
                                |       MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r0
                                |       jne ->exception_handler
                                |       mov r0, EX:RX->func // reload