Skip to content

Commit dc9991b

Browse files
committed
Remove static calls from incompatible $this context
1 parent ff6b4ad commit dc9991b

File tree

5 files changed

+140
-137
lines changed

5 files changed

+140
-137
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
. Fixed oversight where define() did not support arrays yet const syntax did. (Andrea, Dmitry)
3535
. Use "integer" and "float" instead of "long" and "double" in ZPP, type hint and conversion error messages. (Andrea)
3636
. Implemented FR #55428 (E_RECOVERABLE_ERROR when output buffering in output buffering handler). (Kalle)
37+
. Removed scoped calls of non-static methods from an incompatible $this
38+
context. (Nikita)
3739

3840
- Date:
3941
. Fixed day_of_week function as it could sometimes return negative values

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ PHP X.Y UPGRADE NOTES
5454
. zend_function.common.num_args don't include the variadic argument anymore.
5555
. ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an
5656
output buffer is created in an output buffer handler.
57+
. Remove support for scoped calls to non-static methods from an incompatible
58+
$this context. See details in https://wiki.php.net/rfc/incompat_ctx.
5759
. Added zend_memnstr_ex, which is based on string matching sunday algo.
5860
. Added zend_memnrstr, zend_memnrstr_ex.
5961
. Added hybrid sorting algo zend_sort for better performance.

Zend/tests/incompat_ctx_user.phpt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,4 @@ $b->bar();
1616

1717
?>
1818
--EXPECTF--
19-
Deprecated: Non-static method A::foo() should not be called statically, assuming $this from incompatible context in %s on line %d
20-
string(1) "B"
19+
Fatal error: Non-static method A::foo() cannot be called statically, assuming $this from incompatible context in %s on line %d

Zend/zend_vm_def.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2471,24 +2471,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
24712471
object = Z_OBJ(EX(This));
24722472
GC_REFCOUNT(object)++;
24732473
}
2474-
if (!object ||
2475-
!instanceof_function(object->ce, ce)) {
2476-
/* We are calling method of the other (incompatible) class,
2477-
but passing $this. This is done for compatibility with php-4. */
2474+
if (!object) {
24782475
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2479-
zend_error(
2480-
object ? E_DEPRECATED : E_STRICT,
2481-
"Non-static method %s::%s() should not be called statically%s",
2482-
fbc->common.scope->name->val, fbc->common.function_name->val,
2483-
object ? ", assuming $this from incompatible context" : "");
2476+
/* We allow calling userland non-static methods without $this */
2477+
zend_error(E_STRICT,
2478+
"Non-static method %s::%s() should not be called statically",
2479+
fbc->common.scope->name->val, fbc->common.function_name->val);
24842480
} else {
2485-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2486-
zend_error_noreturn(
2487-
E_ERROR,
2488-
"Non-static method %s::%s() cannot be called statically%s",
2489-
fbc->common.scope->name->val, fbc->common.function_name->val,
2490-
object ? ", assuming $this from incompatible context" : "");
2481+
/* An internal function assumes $this is present and won't check that.
2482+
* So PHP would crash by allowing the call. */
2483+
zend_error_noreturn(E_ERROR,
2484+
"Non-static method %s::%s() cannot be called statically",
2485+
fbc->common.scope->name->val, fbc->common.function_name->val);
24912486
}
2487+
} else if (!instanceof_function(object->ce, ce)) {
2488+
zend_error_noreturn(E_ERROR,
2489+
"Non-static method %s::%s() cannot be called statically, "
2490+
"assuming $this from incompatible context",
2491+
fbc->common.scope->name->val, fbc->common.function_name->val);
24922492
}
24932493
}
24942494

Zend/zend_vm_execute.h

Lines changed: 120 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -4257,24 +4257,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(
42574257
object = Z_OBJ(EX(This));
42584258
GC_REFCOUNT(object)++;
42594259
}
4260-
if (!object ||
4261-
!instanceof_function(object->ce, ce)) {
4262-
/* We are calling method of the other (incompatible) class,
4263-
but passing $this. This is done for compatibility with php-4. */
4260+
if (!object) {
42644261
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
4265-
zend_error(
4266-
object ? E_DEPRECATED : E_STRICT,
4267-
"Non-static method %s::%s() should not be called statically%s",
4268-
fbc->common.scope->name->val, fbc->common.function_name->val,
4269-
object ? ", assuming $this from incompatible context" : "");
4262+
/* We allow calling userland non-static methods without $this */
4263+
zend_error(E_STRICT,
4264+
"Non-static method %s::%s() should not be called statically",
4265+
fbc->common.scope->name->val, fbc->common.function_name->val);
42704266
} else {
4271-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
4272-
zend_error_noreturn(
4273-
E_ERROR,
4274-
"Non-static method %s::%s() cannot be called statically%s",
4275-
fbc->common.scope->name->val, fbc->common.function_name->val,
4276-
object ? ", assuming $this from incompatible context" : "");
4267+
/* An internal function assumes $this is present and won't check that.
4268+
* So PHP would crash by allowing the call. */
4269+
zend_error_noreturn(E_ERROR,
4270+
"Non-static method %s::%s() cannot be called statically",
4271+
fbc->common.scope->name->val, fbc->common.function_name->val);
42774272
}
4273+
} else if (!instanceof_function(object->ce, ce)) {
4274+
zend_error_noreturn(E_ERROR,
4275+
"Non-static method %s::%s() cannot be called statically, "
4276+
"assuming $this from incompatible context",
4277+
fbc->common.scope->name->val, fbc->common.function_name->val);
42784278
}
42794279
}
42804280

@@ -6052,24 +6052,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER
60526052
object = Z_OBJ(EX(This));
60536053
GC_REFCOUNT(object)++;
60546054
}
6055-
if (!object ||
6056-
!instanceof_function(object->ce, ce)) {
6057-
/* We are calling method of the other (incompatible) class,
6058-
but passing $this. This is done for compatibility with php-4. */
6055+
if (!object) {
60596056
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
6060-
zend_error(
6061-
object ? E_DEPRECATED : E_STRICT,
6062-
"Non-static method %s::%s() should not be called statically%s",
6063-
fbc->common.scope->name->val, fbc->common.function_name->val,
6064-
object ? ", assuming $this from incompatible context" : "");
6057+
/* We allow calling userland non-static methods without $this */
6058+
zend_error(E_STRICT,
6059+
"Non-static method %s::%s() should not be called statically",
6060+
fbc->common.scope->name->val, fbc->common.function_name->val);
60656061
} else {
6066-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
6067-
zend_error_noreturn(
6068-
E_ERROR,
6069-
"Non-static method %s::%s() cannot be called statically%s",
6070-
fbc->common.scope->name->val, fbc->common.function_name->val,
6071-
object ? ", assuming $this from incompatible context" : "");
6062+
/* An internal function assumes $this is present and won't check that.
6063+
* So PHP would crash by allowing the call. */
6064+
zend_error_noreturn(E_ERROR,
6065+
"Non-static method %s::%s() cannot be called statically",
6066+
fbc->common.scope->name->val, fbc->common.function_name->val);
60726067
}
6068+
} else if (!instanceof_function(object->ce, ce)) {
6069+
zend_error_noreturn(E_ERROR,
6070+
"Non-static method %s::%s() cannot be called statically, "
6071+
"assuming $this from incompatible context",
6072+
fbc->common.scope->name->val, fbc->common.function_name->val);
60736073
}
60746074
}
60756075

@@ -7127,24 +7127,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN
71277127
object = Z_OBJ(EX(This));
71287128
GC_REFCOUNT(object)++;
71297129
}
7130-
if (!object ||
7131-
!instanceof_function(object->ce, ce)) {
7132-
/* We are calling method of the other (incompatible) class,
7133-
but passing $this. This is done for compatibility with php-4. */
7130+
if (!object) {
71347131
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
7135-
zend_error(
7136-
object ? E_DEPRECATED : E_STRICT,
7137-
"Non-static method %s::%s() should not be called statically%s",
7138-
fbc->common.scope->name->val, fbc->common.function_name->val,
7139-
object ? ", assuming $this from incompatible context" : "");
7132+
/* We allow calling userland non-static methods without $this */
7133+
zend_error(E_STRICT,
7134+
"Non-static method %s::%s() should not be called statically",
7135+
fbc->common.scope->name->val, fbc->common.function_name->val);
71407136
} else {
7141-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
7142-
zend_error_noreturn(
7143-
E_ERROR,
7144-
"Non-static method %s::%s() cannot be called statically%s",
7145-
fbc->common.scope->name->val, fbc->common.function_name->val,
7146-
object ? ", assuming $this from incompatible context" : "");
7137+
/* An internal function assumes $this is present and won't check that.
7138+
* So PHP would crash by allowing the call. */
7139+
zend_error_noreturn(E_ERROR,
7140+
"Non-static method %s::%s() cannot be called statically",
7141+
fbc->common.scope->name->val, fbc->common.function_name->val);
71477142
}
7143+
} else if (!instanceof_function(object->ce, ce)) {
7144+
zend_error_noreturn(E_ERROR,
7145+
"Non-static method %s::%s() cannot be called statically, "
7146+
"assuming $this from incompatible context",
7147+
fbc->common.scope->name->val, fbc->common.function_name->val);
71487148
}
71497149
}
71507150

@@ -8265,24 +8265,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER
82658265
object = Z_OBJ(EX(This));
82668266
GC_REFCOUNT(object)++;
82678267
}
8268-
if (!object ||
8269-
!instanceof_function(object->ce, ce)) {
8270-
/* We are calling method of the other (incompatible) class,
8271-
but passing $this. This is done for compatibility with php-4. */
8268+
if (!object) {
82728269
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
8273-
zend_error(
8274-
object ? E_DEPRECATED : E_STRICT,
8275-
"Non-static method %s::%s() should not be called statically%s",
8276-
fbc->common.scope->name->val, fbc->common.function_name->val,
8277-
object ? ", assuming $this from incompatible context" : "");
8270+
/* We allow calling userland non-static methods without $this */
8271+
zend_error(E_STRICT,
8272+
"Non-static method %s::%s() should not be called statically",
8273+
fbc->common.scope->name->val, fbc->common.function_name->val);
82788274
} else {
8279-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
8280-
zend_error_noreturn(
8281-
E_ERROR,
8282-
"Non-static method %s::%s() cannot be called statically%s",
8283-
fbc->common.scope->name->val, fbc->common.function_name->val,
8284-
object ? ", assuming $this from incompatible context" : "");
8275+
/* An internal function assumes $this is present and won't check that.
8276+
* So PHP would crash by allowing the call. */
8277+
zend_error_noreturn(E_ERROR,
8278+
"Non-static method %s::%s() cannot be called statically",
8279+
fbc->common.scope->name->val, fbc->common.function_name->val);
82858280
}
8281+
} else if (!instanceof_function(object->ce, ce)) {
8282+
zend_error_noreturn(E_ERROR,
8283+
"Non-static method %s::%s() cannot be called statically, "
8284+
"assuming $this from incompatible context",
8285+
fbc->common.scope->name->val, fbc->common.function_name->val);
82868286
}
82878287
}
82888288

@@ -13393,24 +13393,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE
1339313393
object = Z_OBJ(EX(This));
1339413394
GC_REFCOUNT(object)++;
1339513395
}
13396-
if (!object ||
13397-
!instanceof_function(object->ce, ce)) {
13398-
/* We are calling method of the other (incompatible) class,
13399-
but passing $this. This is done for compatibility with php-4. */
13396+
if (!object) {
1340013397
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
13401-
zend_error(
13402-
object ? E_DEPRECATED : E_STRICT,
13403-
"Non-static method %s::%s() should not be called statically%s",
13404-
fbc->common.scope->name->val, fbc->common.function_name->val,
13405-
object ? ", assuming $this from incompatible context" : "");
13398+
/* We allow calling userland non-static methods without $this */
13399+
zend_error(E_STRICT,
13400+
"Non-static method %s::%s() should not be called statically",
13401+
fbc->common.scope->name->val, fbc->common.function_name->val);
1340613402
} else {
13407-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
13408-
zend_error_noreturn(
13409-
E_ERROR,
13410-
"Non-static method %s::%s() cannot be called statically%s",
13411-
fbc->common.scope->name->val, fbc->common.function_name->val,
13412-
object ? ", assuming $this from incompatible context" : "");
13403+
/* An internal function assumes $this is present and won't check that.
13404+
* So PHP would crash by allowing the call. */
13405+
zend_error_noreturn(E_ERROR,
13406+
"Non-static method %s::%s() cannot be called statically",
13407+
fbc->common.scope->name->val, fbc->common.function_name->val);
1341313408
}
13409+
} else if (!instanceof_function(object->ce, ce)) {
13410+
zend_error_noreturn(E_ERROR,
13411+
"Non-static method %s::%s() cannot be called statically, "
13412+
"assuming $this from incompatible context",
13413+
fbc->common.scope->name->val, fbc->common.function_name->val);
1341413414
}
1341513415
}
1341613416

@@ -14882,24 +14882,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z
1488214882
object = Z_OBJ(EX(This));
1488314883
GC_REFCOUNT(object)++;
1488414884
}
14885-
if (!object ||
14886-
!instanceof_function(object->ce, ce)) {
14887-
/* We are calling method of the other (incompatible) class,
14888-
but passing $this. This is done for compatibility with php-4. */
14885+
if (!object) {
1488914886
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
14890-
zend_error(
14891-
object ? E_DEPRECATED : E_STRICT,
14892-
"Non-static method %s::%s() should not be called statically%s",
14893-
fbc->common.scope->name->val, fbc->common.function_name->val,
14894-
object ? ", assuming $this from incompatible context" : "");
14887+
/* We allow calling userland non-static methods without $this */
14888+
zend_error(E_STRICT,
14889+
"Non-static method %s::%s() should not be called statically",
14890+
fbc->common.scope->name->val, fbc->common.function_name->val);
1489514891
} else {
14896-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
14897-
zend_error_noreturn(
14898-
E_ERROR,
14899-
"Non-static method %s::%s() cannot be called statically%s",
14900-
fbc->common.scope->name->val, fbc->common.function_name->val,
14901-
object ? ", assuming $this from incompatible context" : "");
14892+
/* An internal function assumes $this is present and won't check that.
14893+
* So PHP would crash by allowing the call. */
14894+
zend_error_noreturn(E_ERROR,
14895+
"Non-static method %s::%s() cannot be called statically",
14896+
fbc->common.scope->name->val, fbc->common.function_name->val);
1490214897
}
14898+
} else if (!instanceof_function(object->ce, ce)) {
14899+
zend_error_noreturn(E_ERROR,
14900+
"Non-static method %s::%s() cannot be called statically, "
14901+
"assuming $this from incompatible context",
14902+
fbc->common.scope->name->val, fbc->common.function_name->val);
1490314903
}
1490414904
}
1490514905

@@ -16329,24 +16329,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_
1632916329
object = Z_OBJ(EX(This));
1633016330
GC_REFCOUNT(object)++;
1633116331
}
16332-
if (!object ||
16333-
!instanceof_function(object->ce, ce)) {
16334-
/* We are calling method of the other (incompatible) class,
16335-
but passing $this. This is done for compatibility with php-4. */
16332+
if (!object) {
1633616333
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
16337-
zend_error(
16338-
object ? E_DEPRECATED : E_STRICT,
16339-
"Non-static method %s::%s() should not be called statically%s",
16340-
fbc->common.scope->name->val, fbc->common.function_name->val,
16341-
object ? ", assuming $this from incompatible context" : "");
16334+
/* We allow calling userland non-static methods without $this */
16335+
zend_error(E_STRICT,
16336+
"Non-static method %s::%s() should not be called statically",
16337+
fbc->common.scope->name->val, fbc->common.function_name->val);
1634216338
} else {
16343-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
16344-
zend_error_noreturn(
16345-
E_ERROR,
16346-
"Non-static method %s::%s() cannot be called statically%s",
16347-
fbc->common.scope->name->val, fbc->common.function_name->val,
16348-
object ? ", assuming $this from incompatible context" : "");
16339+
/* An internal function assumes $this is present and won't check that.
16340+
* So PHP would crash by allowing the call. */
16341+
zend_error_noreturn(E_ERROR,
16342+
"Non-static method %s::%s() cannot be called statically",
16343+
fbc->common.scope->name->val, fbc->common.function_name->val);
1634916344
}
16345+
} else if (!instanceof_function(object->ce, ce)) {
16346+
zend_error_noreturn(E_ERROR,
16347+
"Non-static method %s::%s() cannot be called statically, "
16348+
"assuming $this from incompatible context",
16349+
fbc->common.scope->name->val, fbc->common.function_name->val);
1635016350
}
1635116351
}
1635216352

@@ -17766,24 +17766,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(Z
1776617766
object = Z_OBJ(EX(This));
1776717767
GC_REFCOUNT(object)++;
1776817768
}
17769-
if (!object ||
17770-
!instanceof_function(object->ce, ce)) {
17771-
/* We are calling method of the other (incompatible) class,
17772-
but passing $this. This is done for compatibility with php-4. */
17769+
if (!object) {
1777317770
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
17774-
zend_error(
17775-
object ? E_DEPRECATED : E_STRICT,
17776-
"Non-static method %s::%s() should not be called statically%s",
17777-
fbc->common.scope->name->val, fbc->common.function_name->val,
17778-
object ? ", assuming $this from incompatible context" : "");
17771+
/* We allow calling userland non-static methods without $this */
17772+
zend_error(E_STRICT,
17773+
"Non-static method %s::%s() should not be called statically",
17774+
fbc->common.scope->name->val, fbc->common.function_name->val);
1777917775
} else {
17780-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
17781-
zend_error_noreturn(
17782-
E_ERROR,
17783-
"Non-static method %s::%s() cannot be called statically%s",
17784-
fbc->common.scope->name->val, fbc->common.function_name->val,
17785-
object ? ", assuming $this from incompatible context" : "");
17776+
/* An internal function assumes $this is present and won't check that.
17777+
* So PHP would crash by allowing the call. */
17778+
zend_error_noreturn(E_ERROR,
17779+
"Non-static method %s::%s() cannot be called statically",
17780+
fbc->common.scope->name->val, fbc->common.function_name->val);
1778617781
}
17782+
} else if (!instanceof_function(object->ce, ce)) {
17783+
zend_error_noreturn(E_ERROR,
17784+
"Non-static method %s::%s() cannot be called statically, "
17785+
"assuming $this from incompatible context",
17786+
fbc->common.scope->name->val, fbc->common.function_name->val);
1778717787
}
1778817788
}
1778917789

0 commit comments

Comments
 (0)