com php-src: Fixed bug #76430: NEWS Zend/tests/bug76430.phpt Zend/tests/nested_method_and_function.phpt Zend/zend _compile.c

From: Date: Tue, 12 Feb 2019 16:36:07 +0000
Subject: com php-src: Fixed bug #76430: NEWS Zend/tests/bug76430.phpt Zend/tests/nested_method_and_function.phpt Zend/zend _compile.c
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-104607@lists.php.net to get a copy of this message
Commit: 93641539429c41a8997016ee4a4502882b0a722e Author: Nikita Popov <nikita.ppv@gmail.com> Tue, 12 Feb 2019 17:34:55 +0100 Parents: d77ad27415a34e4f5908cb262567b7b6f0eca17f Branches: PHP-7.4 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=93641539429c41a8997016ee4a4502882b0a722e Log: 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. Bugs: https://bugs.php.net/76430 Changed paths: M NEWS A Zend/tests/bug76430.phpt M Zend/tests/nested_method_and_function.phpt M Zend/zend_compile.c Diff: diff --git a/NEWS b/NEWS index 2a76ca3..65997b0 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,8 @@ PHP NEWS - Core: . Implemented request #76148 (Add array_key_exists() to the list of specially compiled functions). (Majkl578) - . Fixed bug #77546 (iptcembed broken function). (gdegoulet) + . Fixed bug #76430 (__METHOD__ inconsistent outside of method). + (Ryan McCullagh, Nikita) - CURL: . Fixed bug #76480 (Use curl_multi_wait() so that timeouts are respected). diff --git a/Zend/tests/bug76430.phpt b/Zend/tests/bug76430.phpt new file mode 100644 index 0000000..f122d00 --- /dev/null +++ b/Zend/tests/bug76430.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #76430: __METHOD__ inconsistent outside of method +--FILE-- +<?php + +class Foo { + const X = __METHOD__; +} +function foo() { + class Bar { + const X = __METHOD__; + } +} + +foo(); +var_dump(Foo::X); +var_dump(Bar::X); + +?> +--EXPECT-- +string(0) "" +string(0) "" diff --git a/Zend/tests/nested_method_and_function.phpt b/Zend/tests/nested_method_and_function.phpt index c63c601..3d19a06 100644 --- a/Zend/tests/nested_method_and_function.phpt +++ b/Zend/tests/nested_method_and_function.phpt @@ -30,7 +30,7 @@ $c(); --EXPECT-- string(7) "Baz\foo" string(7) "Baz\foo" -string(7) "Baz\Foo" +string(0) "" string(3) "bar" string(12) "Baz\Foo::bar" string(7) "Baz\Foo" diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index cb7b30c..cb961be 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5784,6 +5784,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* zend_ast *return_type_ast = decl->child[3]; zend_bool is_method = decl->kind == ZEND_AST_METHOD; + zend_class_entry *orig_class_entry = CG(active_class_entry); zend_op_array *orig_op_array = CG(active_op_array); zend_op_array *op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); zend_oparray_context orig_oparray_context; @@ -5816,6 +5817,13 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* CG(active_op_array) = op_array; + /* Do not leak the class scope into free standing functions, even if they are dynamically + * defined inside a class method. This is necessary for correct handling of magic constants.. + * For example __CLASS__ should always be "" inside a free standing function. */ + if (decl->kind == ZEND_AST_FUNC_DECL) { + CG(active_class_entry) = NULL; + } + if (toplevel) { op_array->fn_flags |= ZEND_ACC_TOP_LEVEL; } @@ -5863,6 +5871,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast, zend_bool toplevel) /* zend_stack_del_top(&CG(loop_var_stack)); CG(active_op_array) = orig_op_array; + CG(active_class_entry) = orig_class_entry; } /* }}} */ @@ -6724,17 +6733,20 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */ } break; case T_METHOD_C: - if ((op_array && !op_array->scope && op_array->function_name) || (op_array->fn_flags & ZEND_ACC_CLOSURE)) { - ZVAL_STR_COPY(zv, op_array->function_name); - } else if (ce) { - if (op_array && op_array->function_name) { - ZVAL_NEW_STR(zv, zend_concat3(ZSTR_VAL(ce->name), ZSTR_LEN(ce->name), "::", 2, + /* Detect whether we are directly inside a class (e.g. a class constant) and treat + * this as not being inside a function. */ + if (op_array && ce && !op_array->scope && !(op_array->fn_flags & ZEND_ACC_CLOSURE)) { + op_array = NULL; + } + if (op_array && op_array->function_name) { + if (op_array->scope) { + ZVAL_NEW_STR(zv, zend_concat3( + ZSTR_VAL(op_array->scope->name), ZSTR_LEN(op_array->scope->name), + "::", 2, ZSTR_VAL(op_array->function_name), ZSTR_LEN(op_array->function_name))); } else { - ZVAL_STR_COPY(zv, ce->name); + ZVAL_STR_COPY(zv, op_array->function_name); } - } else if (op_array && op_array->function_name) { - ZVAL_STR_COPY(zv, op_array->function_name); } else { ZVAL_EMPTY_STRING(zv); }

« previous php.cvs (#104607) next »