Skip to content

Commit 9364153

Browse files
committed
Fixed bug #76430
It's somewhat ambiguous what exactly the correct behavior is supposed to be, I'm just picking something more or less reasonable here.
1 parent d77ad27 commit 9364153

File tree

4 files changed

+45
-10
lines changed

4 files changed

+45
-10
lines changed

NEWS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ PHP NEWS
55
- Core:
66
. Implemented request #76148 (Add array_key_exists() to the list of
77
specially compiled functions). (Majkl578)
8-
. Fixed bug #77546 (iptcembed broken function). (gdegoulet)
8+
. Fixed bug #76430 (__METHOD__ inconsistent outside of method).
9+
(Ryan McCullagh, Nikita)
910

1011
- CURL:
1112
. Fixed bug #76480 (Use curl_multi_wait() so that timeouts are respected).

Zend/tests/bug76430.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #76430: __METHOD__ inconsistent outside of method
3+
--FILE--
4+
<?php
5+
6+
class Foo {
7+
const X = __METHOD__;
8+
}
9+
function foo() {
10+
class Bar {
11+
const X = __METHOD__;
12+
}
13+
}
14+
15+
foo();
16+
var_dump(Foo::X);
17+
var_dump(Bar::X);
18+
19+
?>
20+
--EXPECT--
21+
string(0) ""
22+
string(0) ""

Zend/tests/nested_method_and_function.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ $c();
3030
--EXPECT--
3131
string(7) "Baz\foo"
3232
string(7) "Baz\foo"
33-
string(7) "Baz\Foo"
33+
string(0) ""
3434
string(3) "bar"
3535
string(12) "Baz\Foo::bar"
3636
string(7) "Baz\Foo"

Zend/zend_compile.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5784,6 +5784,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
57845784
zend_ast *return_type_ast = decl->child[3];
57855785
zend_bool is_method = decl->kind == ZEND_AST_METHOD;
57865786

5787+
zend_class_entry *orig_class_entry = CG(active_class_entry);
57875788
zend_op_array *orig_op_array = CG(active_op_array);
57885789
zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
57895790
zend_oparray_context orig_oparray_context;
@@ -5816,6 +5817,13 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
58165817

58175818
CG(active_op_array) = op_array;
58185819

5820+
/* Do not leak the class scope into free standing functions, even if they are dynamically
5821+
* defined inside a class method. This is necessary for correct handling of magic constants.
5822+
* For example __CLASS__ should always be "" inside a free standing function. */
5823+
if (decl->kind == ZEND_AST_FUNC_DECL) {
5824+
CG(active_class_entry) = NULL;
5825+
}
5826+
58195827
if (toplevel) {
58205828
op_array->fn_flags |= ZEND_ACC_TOP_LEVEL;
58215829
}
@@ -5863,6 +5871,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /*
58635871
zend_stack_del_top(&CG(loop_var_stack));
58645872

58655873
CG(active_op_array) = orig_op_array;
5874+
CG(active_class_entry) = orig_class_entry;
58665875
}
58675876
/* }}} */
58685877

@@ -6724,17 +6733,20 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */
67246733
}
67256734
break;
67266735
case T_METHOD_C:
6727-
if ((op_array && !op_array->scope && op_array->function_name) || (op_array->fn_flags & ZEND_ACC_CLOSURE)) {
6728-
ZVAL_STR_COPY(zv, op_array->function_name);
6729-
} else if (ce) {
6730-
if (op_array && op_array->function_name) {
6731-
ZVAL_NEW_STR(zv, zend_concat3(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::", 2,
6736+
/* Detect whether we are directly inside a class (e.g. a class constant) and treat
6737+
* this as not being inside a function. */
6738+
if (op_array && ce && !op_array->scope && !(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
6739+
op_array = NULL;
6740+
}
6741+
if (op_array && op_array->function_name) {
6742+
if (op_array->scope) {
6743+
ZVAL_NEW_STR(zv, zend_concat3(
6744+
ZSTR_VAL(op_array->scope->name), ZSTR_LEN(op_array->scope->name),
6745+
"::", 2,
67326746
ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name)));
67336747
} else {
6734-
ZVAL_STR_COPY(zv, ce->name);
6748+
ZVAL_STR_COPY(zv, op_array->function_name);
67356749
}
6736-
} else if (op_array && op_array->function_name) {
6737-
ZVAL_STR_COPY(zv, op_array->function_name);
67386750
} else {
67396751
ZVAL_EMPTY_STRING(zv);
67406752
}

0 commit comments

Comments
 (0)