From dc9991b167533c7ee13ff96da6048988e6e31bc2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 10 Sep 2014 16:08:20 +0200 Subject: [PATCH] Remove static calls from incompatible $this context --- NEWS | 2 + UPGRADING | 2 + Zend/tests/incompat_ctx_user.phpt | 3 +- Zend/zend_vm_def.h | 30 ++-- Zend/zend_vm_execute.h | 240 +++++++++++++++--------------- 5 files changed, 140 insertions(+), 137 deletions(-) diff --git a/NEWS b/NEWS index 721a1ccf20..6c9985d646 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ . Fixed oversight where define() did not support arrays yet const syntax did. (Andrea, Dmitry) . Use "integer" and "float" instead of "long" and "double" in ZPP, type hint and conversion error messages. (Andrea) . Implemented FR #55428 (E_RECOVERABLE_ERROR when output buffering in output buffering handler). (Kalle) + . Removed scoped calls of non-static methods from an incompatible $this + context. (Nikita) - Date: . Fixed day_of_week function as it could sometimes return negative values diff --git a/UPGRADING b/UPGRADING index 8506ba7ca5..71197f9e3d 100644 --- a/UPGRADING +++ b/UPGRADING @@ -54,6 +54,8 @@ PHP X.Y UPGRADE NOTES . zend_function.common.num_args don't include the variadic argument anymore. . ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an output buffer is created in an output buffer handler. + . Remove support for scoped calls to non-static methods from an incompatible + $this context. See details in https://wiki.php.net/rfc/incompat_ctx. . Added zend_memnstr_ex, which is based on string matching sunday algo. . Added zend_memnrstr, zend_memnrstr_ex. . Added hybrid sorting algo zend_sort for better performance. diff --git a/Zend/tests/incompat_ctx_user.phpt b/Zend/tests/incompat_ctx_user.phpt index 2d9b59c1e8..5923d5a702 100644 --- a/Zend/tests/incompat_ctx_user.phpt +++ b/Zend/tests/incompat_ctx_user.phpt @@ -16,5 +16,4 @@ $b->bar(); ?> --EXPECTF-- -Deprecated: Non-static method A::foo() should not be called statically, assuming $this from incompatible context in %s on line %d -string(1) "B" +Fatal error: Non-static method A::foo() cannot be called statically, assuming $this from incompatible context in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index dc3547a5e2..0958002f43 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2471,24 +2471,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1d56205e08..da9636eaaa 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4257,24 +4257,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -6052,24 +6052,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -7127,24 +7127,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -8265,24 +8265,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -13393,24 +13393,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -14882,24 +14882,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -16329,24 +16329,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } @@ -17766,24 +17766,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z object = Z_OBJ(EX(This)); GC_REFCOUNT(object)++; } - if (!object || - !instanceof_function(object->ce, ce)) { - /* We are calling method of the other (incompatible) class, - but passing $this. This is done for compatibility with php-4. */ + if (!object) { if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error( - object ? E_DEPRECATED : E_STRICT, - "Non-static method %s::%s() should not be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* We allow calling userland non-static methods without $this */ + zend_error(E_STRICT, + "Non-static method %s::%s() should not be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } else { - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn( - E_ERROR, - "Non-static method %s::%s() cannot be called statically%s", - fbc->common.scope->name->val, fbc->common.function_name->val, - object ? ", assuming $this from incompatible context" : ""); + /* An internal function assumes $this is present and won't check that. + * So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically", + fbc->common.scope->name->val, fbc->common.function_name->val); } + } else if (!instanceof_function(object->ce, ce)) { + zend_error_noreturn(E_ERROR, + "Non-static method %s::%s() cannot be called statically, " + "assuming $this from incompatible context", + fbc->common.scope->name->val, fbc->common.function_name->val); } } -- 2.40.0