Skip to content

Commit 0857749

Browse files
committed
Drop support for static calls from incompatible context
Implemented by NULLing $this.
1 parent 7c67727 commit 0857749

File tree

5 files changed

+92
-131
lines changed

5 files changed

+92
-131
lines changed

Zend/tests/bug46381.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ $test->method();
1414
echo "Done\n";
1515
?>
1616
--EXPECTF--
17-
Fatal error: Non-static method ArrayIterator::current() cannot be called statically, assuming $this from incompatible context in %s on line %d
17+
Fatal error: Non-static method ArrayIterator::current() cannot be called statically in %s on line %d

Zend/tests/incompat_ctx_user.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
Incompatible context call (non-internal function)
3-
--INI--
4-
error_reporting=E_ALL
53
--FILE--
64
<?php
75

@@ -16,5 +14,7 @@ $b->bar();
1614

1715
?>
1816
--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"
17+
Deprecated: Non-static method A::foo() should not be called statically in %s on line %d
18+
19+
Notice: Undefined variable: this in %s on line %d
20+
string(1) "A"

Zend/zend_API.c

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,25 +3108,13 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
31083108
if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0) {
31093109
retval = 0;
31103110
}
3111-
if (EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope)) {
3112-
fcc->object = Z_OBJ(EG(current_execute_data)->This);
3113-
if (error) {
3114-
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(current_execute_data)->This)->name->val);
3115-
if (severity == E_ERROR) {
3116-
retval = 0;
3117-
}
3118-
} else if (retval) {
3119-
zend_error(severity, "Non-static method %s::%s() %s be called statically, assuming $this from compatible context %s", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb, Z_OBJCE(EG(current_execute_data)->This)->name->val);
3120-
}
3121-
} else {
3122-
if (error) {
3123-
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb);
3124-
if (severity == E_ERROR) {
3125-
retval = 0;
3126-
}
3127-
} else if (retval) {
3128-
zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb);
3111+
if (error) {
3112+
zend_spprintf(error, 0, "non-static method %s::%s() %s be called statically", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb);
3113+
if (severity == E_ERROR) {
3114+
retval = 0;
31293115
}
3116+
} else if (retval) {
3117+
zend_error(severity, "Non-static method %s::%s() %s be called statically", fcc->calling_scope->name->val, fcc->function_handler->common.function_name->val, verb);
31303118
}
31313119
}
31323120
if (retval && (check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {

Zend/zend_vm_def.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,27 +2926,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
29262926

29272927
object = NULL;
29282928
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
2929-
if (Z_OBJ(EX(This))) {
2929+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
29302930
object = Z_OBJ(EX(This));
29312931
GC_REFCOUNT(object)++;
29322932
}
2933-
if (!object ||
2934-
!instanceof_function(object->ce, ce)) {
2935-
/* We are calling method of the other (incompatible) class,
2936-
but passing $this. This is done for compatibility with php-4. */
2933+
if (!object) {
29372934
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2935+
/* Allowed for PHP 4 compatibility. */
29382936
zend_error(
29392937
E_DEPRECATED,
2940-
"Non-static method %s::%s() should not be called statically%s",
2941-
fbc->common.scope->name->val, fbc->common.function_name->val,
2942-
object ? ", assuming $this from incompatible context" : "");
2938+
"Non-static method %s::%s() should not be called statically",
2939+
fbc->common.scope->name->val, fbc->common.function_name->val);
29432940
} else {
2944-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2941+
/* An internal function assumes $this is present and won't check that.
2942+
* So PHP would crash by allowing the call. */
29452943
zend_error(
29462944
E_EXCEPTION | E_ERROR,
2947-
"Non-static method %s::%s() cannot be called statically%s",
2948-
fbc->common.scope->name->val, fbc->common.function_name->val,
2949-
object ? ", assuming $this from incompatible context" : "");
2945+
"Non-static method %s::%s() cannot be called statically",
2946+
fbc->common.scope->name->val, fbc->common.function_name->val);
29502947
HANDLE_EXCEPTION();
29512948
}
29522949
}

Zend/zend_vm_execute.h

Lines changed: 72 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5065,27 +5065,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
50655065

50665066
object = NULL;
50675067
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
5068-
if (Z_OBJ(EX(This))) {
5068+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
50695069
object = Z_OBJ(EX(This));
50705070
GC_REFCOUNT(object)++;
50715071
}
5072-
if (!object ||
5073-
!instanceof_function(object->ce, ce)) {
5074-
/* We are calling method of the other (incompatible) class,
5075-
but passing $this. This is done for compatibility with php-4. */
5072+
if (!object) {
50765073
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
5074+
/* Allowed for PHP 4 compatibility. */
50775075
zend_error(
50785076
E_DEPRECATED,
5079-
"Non-static method %s::%s() should not be called statically%s",
5080-
fbc->common.scope->name->val, fbc->common.function_name->val,
5081-
object ? ", assuming $this from incompatible context" : "");
5077+
"Non-static method %s::%s() should not be called statically",
5078+
fbc->common.scope->name->val, fbc->common.function_name->val);
50825079
} else {
5083-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
5080+
/* An internal function assumes $this is present and won't check that.
5081+
* So PHP would crash by allowing the call. */
50845082
zend_error(
50855083
E_EXCEPTION | E_ERROR,
5086-
"Non-static method %s::%s() cannot be called statically%s",
5087-
fbc->common.scope->name->val, fbc->common.function_name->val,
5088-
object ? ", assuming $this from incompatible context" : "");
5084+
"Non-static method %s::%s() cannot be called statically",
5085+
fbc->common.scope->name->val, fbc->common.function_name->val);
50895086
HANDLE_EXCEPTION();
50905087
}
50915088
}
@@ -6989,27 +6986,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
69896986

69906987
object = NULL;
69916988
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
6992-
if (Z_OBJ(EX(This))) {
6989+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
69936990
object = Z_OBJ(EX(This));
69946991
GC_REFCOUNT(object)++;
69956992
}
6996-
if (!object ||
6997-
!instanceof_function(object->ce, ce)) {
6998-
/* We are calling method of the other (incompatible) class,
6999-
but passing $this. This is done for compatibility with php-4. */
6993+
if (!object) {
70006994
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
6995+
/* Allowed for PHP 4 compatibility. */
70016996
zend_error(
70026997
E_DEPRECATED,
7003-
"Non-static method %s::%s() should not be called statically%s",
7004-
fbc->common.scope->name->val, fbc->common.function_name->val,
7005-
object ? ", assuming $this from incompatible context" : "");
6998+
"Non-static method %s::%s() should not be called statically",
6999+
fbc->common.scope->name->val, fbc->common.function_name->val);
70067000
} else {
7007-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
7001+
/* An internal function assumes $this is present and won't check that.
7002+
* So PHP would crash by allowing the call. */
70087003
zend_error(
70097004
E_EXCEPTION | E_ERROR,
7010-
"Non-static method %s::%s() cannot be called statically%s",
7011-
fbc->common.scope->name->val, fbc->common.function_name->val,
7012-
object ? ", assuming $this from incompatible context" : "");
7005+
"Non-static method %s::%s() cannot be called statically",
7006+
fbc->common.scope->name->val, fbc->common.function_name->val);
70137007
HANDLE_EXCEPTION();
70147008
}
70157009
}
@@ -8473,27 +8467,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
84738467

84748468
object = NULL;
84758469
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
8476-
if (Z_OBJ(EX(This))) {
8470+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
84778471
object = Z_OBJ(EX(This));
84788472
GC_REFCOUNT(object)++;
84798473
}
8480-
if (!object ||
8481-
!instanceof_function(object->ce, ce)) {
8482-
/* We are calling method of the other (incompatible) class,
8483-
but passing $this. This is done for compatibility with php-4. */
8474+
if (!object) {
84848475
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
8476+
/* Allowed for PHP 4 compatibility. */
84858477
zend_error(
84868478
E_DEPRECATED,
8487-
"Non-static method %s::%s() should not be called statically%s",
8488-
fbc->common.scope->name->val, fbc->common.function_name->val,
8489-
object ? ", assuming $this from incompatible context" : "");
8479+
"Non-static method %s::%s() should not be called statically",
8480+
fbc->common.scope->name->val, fbc->common.function_name->val);
84908481
} else {
8491-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
8482+
/* An internal function assumes $this is present and won't check that.
8483+
* So PHP would crash by allowing the call. */
84928484
zend_error(
84938485
E_EXCEPTION | E_ERROR,
8494-
"Non-static method %s::%s() cannot be called statically%s",
8495-
fbc->common.scope->name->val, fbc->common.function_name->val,
8496-
object ? ", assuming $this from incompatible context" : "");
8486+
"Non-static method %s::%s() cannot be called statically",
8487+
fbc->common.scope->name->val, fbc->common.function_name->val);
84978488
HANDLE_EXCEPTION();
84988489
}
84998490
}
@@ -10020,27 +10011,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
1002010011

1002110012
object = NULL;
1002210013
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
10023-
if (Z_OBJ(EX(This))) {
10014+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
1002410015
object = Z_OBJ(EX(This));
1002510016
GC_REFCOUNT(object)++;
1002610017
}
10027-
if (!object ||
10028-
!instanceof_function(object->ce, ce)) {
10029-
/* We are calling method of the other (incompatible) class,
10030-
but passing $this. This is done for compatibility with php-4. */
10018+
if (!object) {
1003110019
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
10020+
/* Allowed for PHP 4 compatibility. */
1003210021
zend_error(
1003310022
E_DEPRECATED,
10034-
"Non-static method %s::%s() should not be called statically%s",
10035-
fbc->common.scope->name->val, fbc->common.function_name->val,
10036-
object ? ", assuming $this from incompatible context" : "");
10023+
"Non-static method %s::%s() should not be called statically",
10024+
fbc->common.scope->name->val, fbc->common.function_name->val);
1003710025
} else {
10038-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
10026+
/* An internal function assumes $this is present and won't check that.
10027+
* So PHP would crash by allowing the call. */
1003910028
zend_error(
1004010029
E_EXCEPTION | E_ERROR,
10041-
"Non-static method %s::%s() cannot be called statically%s",
10042-
fbc->common.scope->name->val, fbc->common.function_name->val,
10043-
object ? ", assuming $this from incompatible context" : "");
10030+
"Non-static method %s::%s() cannot be called statically",
10031+
fbc->common.scope->name->val, fbc->common.function_name->val);
1004410032
HANDLE_EXCEPTION();
1004510033
}
1004610034
}
@@ -15880,27 +15868,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
1588015868

1588115869
object = NULL;
1588215870
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
15883-
if (Z_OBJ(EX(This))) {
15871+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
1588415872
object = Z_OBJ(EX(This));
1588515873
GC_REFCOUNT(object)++;
1588615874
}
15887-
if (!object ||
15888-
!instanceof_function(object->ce, ce)) {
15889-
/* We are calling method of the other (incompatible) class,
15890-
but passing $this. This is done for compatibility with php-4. */
15875+
if (!object) {
1589115876
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
15877+
/* Allowed for PHP 4 compatibility. */
1589215878
zend_error(
1589315879
E_DEPRECATED,
15894-
"Non-static method %s::%s() should not be called statically%s",
15895-
fbc->common.scope->name->val, fbc->common.function_name->val,
15896-
object ? ", assuming $this from incompatible context" : "");
15880+
"Non-static method %s::%s() should not be called statically",
15881+
fbc->common.scope->name->val, fbc->common.function_name->val);
1589715882
} else {
15898-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
15883+
/* An internal function assumes $this is present and won't check that.
15884+
* So PHP would crash by allowing the call. */
1589915885
zend_error(
1590015886
E_EXCEPTION | E_ERROR,
15901-
"Non-static method %s::%s() cannot be called statically%s",
15902-
fbc->common.scope->name->val, fbc->common.function_name->val,
15903-
object ? ", assuming $this from incompatible context" : "");
15887+
"Non-static method %s::%s() cannot be called statically",
15888+
fbc->common.scope->name->val, fbc->common.function_name->val);
1590415889
HANDLE_EXCEPTION();
1590515890
}
1590615891
}
@@ -17453,27 +17438,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
1745317438

1745417439
object = NULL;
1745517440
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
17456-
if (Z_OBJ(EX(This))) {
17441+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
1745717442
object = Z_OBJ(EX(This));
1745817443
GC_REFCOUNT(object)++;
1745917444
}
17460-
if (!object ||
17461-
!instanceof_function(object->ce, ce)) {
17462-
/* We are calling method of the other (incompatible) class,
17463-
but passing $this. This is done for compatibility with php-4. */
17445+
if (!object) {
1746417446
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
17447+
/* Allowed for PHP 4 compatibility. */
1746517448
zend_error(
1746617449
E_DEPRECATED,
17467-
"Non-static method %s::%s() should not be called statically%s",
17468-
fbc->common.scope->name->val, fbc->common.function_name->val,
17469-
object ? ", assuming $this from incompatible context" : "");
17450+
"Non-static method %s::%s() should not be called statically",
17451+
fbc->common.scope->name->val, fbc->common.function_name->val);
1747017452
} else {
17471-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
17453+
/* An internal function assumes $this is present and won't check that.
17454+
* So PHP would crash by allowing the call. */
1747217455
zend_error(
1747317456
E_EXCEPTION | E_ERROR,
17474-
"Non-static method %s::%s() cannot be called statically%s",
17475-
fbc->common.scope->name->val, fbc->common.function_name->val,
17476-
object ? ", assuming $this from incompatible context" : "");
17457+
"Non-static method %s::%s() cannot be called statically",
17458+
fbc->common.scope->name->val, fbc->common.function_name->val);
1747717459
HANDLE_EXCEPTION();
1747817460
}
1747917461
}
@@ -19068,27 +19050,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
1906819050

1906919051
object = NULL;
1907019052
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
19071-
if (Z_OBJ(EX(This))) {
19053+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
1907219054
object = Z_OBJ(EX(This));
1907319055
GC_REFCOUNT(object)++;
1907419056
}
19075-
if (!object ||
19076-
!instanceof_function(object->ce, ce)) {
19077-
/* We are calling method of the other (incompatible) class,
19078-
but passing $this. This is done for compatibility with php-4. */
19057+
if (!object) {
1907919058
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
19059+
/* Allowed for PHP 4 compatibility. */
1908019060
zend_error(
1908119061
E_DEPRECATED,
19082-
"Non-static method %s::%s() should not be called statically%s",
19083-
fbc->common.scope->name->val, fbc->common.function_name->val,
19084-
object ? ", assuming $this from incompatible context" : "");
19062+
"Non-static method %s::%s() should not be called statically",
19063+
fbc->common.scope->name->val, fbc->common.function_name->val);
1908519064
} else {
19086-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
19065+
/* An internal function assumes $this is present and won't check that.
19066+
* So PHP would crash by allowing the call. */
1908719067
zend_error(
1908819068
E_EXCEPTION | E_ERROR,
19089-
"Non-static method %s::%s() cannot be called statically%s",
19090-
fbc->common.scope->name->val, fbc->common.function_name->val,
19091-
object ? ", assuming $this from incompatible context" : "");
19069+
"Non-static method %s::%s() cannot be called statically",
19070+
fbc->common.scope->name->val, fbc->common.function_name->val);
1909219071
HANDLE_EXCEPTION();
1909319072
}
1909419073
}
@@ -20625,27 +20604,24 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
2062520604

2062620605
object = NULL;
2062720606
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
20628-
if (Z_OBJ(EX(This))) {
20607+
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
2062920608
object = Z_OBJ(EX(This));
2063020609
GC_REFCOUNT(object)++;
2063120610
}
20632-
if (!object ||
20633-
!instanceof_function(object->ce, ce)) {
20634-
/* We are calling method of the other (incompatible) class,
20635-
but passing $this. This is done for compatibility with php-4. */
20611+
if (!object) {
2063620612
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
20613+
/* Allowed for PHP 4 compatibility. */
2063720614
zend_error(
2063820615
E_DEPRECATED,
20639-
"Non-static method %s::%s() should not be called statically%s",
20640-
fbc->common.scope->name->val, fbc->common.function_name->val,
20641-
object ? ", assuming $this from incompatible context" : "");
20616+
"Non-static method %s::%s() should not be called statically",
20617+
fbc->common.scope->name->val, fbc->common.function_name->val);
2064220618
} else {
20643-
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
20619+
/* An internal function assumes $this is present and won't check that.
20620+
* So PHP would crash by allowing the call. */
2064420621
zend_error(
2064520622
E_EXCEPTION | E_ERROR,
20646-
"Non-static method %s::%s() cannot be called statically%s",
20647-
fbc->common.scope->name->val, fbc->common.function_name->val,
20648-
object ? ", assuming $this from incompatible context" : "");
20623+
"Non-static method %s::%s() cannot be called statically",
20624+
fbc->common.scope->name->val, fbc->common.function_name->val);
2064920625
HANDLE_EXCEPTION();
2065020626
}
2065120627
}

0 commit comments

Comments
 (0)