From 1e5aff9522c74ed77e27cb62a9618d8e0f0b4285 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 10 Jan 2009 19:14:27 +0000 Subject: [PATCH] - Fixed bug #47054 (BC break in static functions called as dynamic) --- Zend/tests/bug47054.phpt | 39 ++++++++++++ Zend/zend_builtin_functions.c | 4 +- Zend/zend_vm_def.h | 9 ++- Zend/zend_vm_execute.h | 112 ++++++++++++++++++++++++---------- 4 files changed, 127 insertions(+), 37 deletions(-) create mode 100644 Zend/tests/bug47054.phpt diff --git a/Zend/tests/bug47054.phpt b/Zend/tests/bug47054.phpt new file mode 100644 index 0000000000..ab6c6e1de4 --- /dev/null +++ b/Zend/tests/bug47054.phpt @@ -0,0 +1,39 @@ +--TEST-- +Bug #47054 (BC break in static functions called as dynamic) +--FILE-- +s(); + } +} + +$d = new D(); +$d->m(); + +C::s(); + +$c = new C(); +$c->s(); + +get_called_class(); + +D::m(); + +?> +--EXPECTF-- +Called class: D +Called class: C +Called class: C + +Warning: get_called_class() called from outside a class in %s on line %d + +Strict Standards: Non-static method D::m() should not be called statically in %s on line %d + +Fatal error: Using $this when not in object context in %s on line %d diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index d8ffc81e23..f976c7500b 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -743,10 +743,10 @@ ZEND_FUNCTION(get_called_class) if (EG(called_scope)) { RETURN_TEXTL(EG(called_scope)->name, EG(called_scope)->name_length, 1); - } else { + } else if (!EG(scope)) { zend_error(E_WARNING, "get_called_class() called from outside a class"); - RETURN_FALSE; } + RETURN_FALSE; } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8177ec6b3b..34b7707f62 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1977,15 +1977,18 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; - } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; + } else { if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6153fbe092..dc13bb495d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -6193,15 +6193,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -6666,15 +6669,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -7141,15 +7147,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -7711,15 +7720,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -10719,15 +10731,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -12632,15 +12647,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -14529,15 +14547,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -17046,15 +17067,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -18480,15 +18504,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -19680,15 +19707,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -20812,15 +20842,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -22213,15 +22246,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -25248,15 +25284,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -26970,15 +27009,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -28744,15 +28786,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { @@ -31026,15 +31071,18 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H if (!EX(fbc)) { zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval); } + + EX(called_scope) = Z_OBJCE_P(EX(object)); } else { zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval); } - if (!EX(object) || (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + if (!EX(object)) { EX(called_scope) = NULL; EX(object) = NULL; + } else if (EX(fbc) && (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { + EX(object) = NULL; } else { - EX(called_scope) = Z_OBJCE_P(EX(object)); if (!PZVAL_IS_REF(EX(object))) { Z_ADDREF_P(EX(object)); /* For $this pointer */ } else { -- 2.50.1