Adjust filename/lineno for constant expressions

Closes GH-7771
Closes GH-8124
This commit is contained in:
Ilija Tovilo 2022-02-05 13:00:17 +01:00
parent 634b2141de
commit e3ef7bbbb8
No known key found for this signature in database
GPG Key ID: A4F5D403F118200A
9 changed files with 80 additions and 11 deletions

1
NEWS
View File

@ -7,6 +7,7 @@ PHP NEWS
- Core: - Core:
. Fixed bug #81380 (Observer may not be initialized properly). (krakjoe) . Fixed bug #81380 (Observer may not be initialized properly). (krakjoe)
. Fixed bug GH-7771 (Fix filename/lineno of constant expressions). (ilutov)
- Intl: - Intl:
. Update all grandfathered language tags with preferred values . Update all grandfathered language tags with preferred values

View File

@ -11,4 +11,4 @@ echo Foo::A."\n";
Fatal error: Uncaught Error: Undefined constant self::B in %s:%d Fatal error: Uncaught Error: Undefined constant self::B in %s:%d
Stack trace: Stack trace:
#0 {main} #0 {main}
thrown in %sbug41633_2.php on line 5 thrown in %sbug41633_2.php on line 3

15
Zend/tests/gh7771_1.phpt Normal file
View File

@ -0,0 +1,15 @@
--TEST--
GH-7771 (Incorrect file/line for class constant expression exceptions)
--FILE--
<?php
include __DIR__ . '/gh7771_1_definition.inc';
new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Class "NonExistent" not found in %sgh7771_1_definition.inc:4
Stack trace:
#0 {main}
thrown in %sgh7771_1_definition.inc on line 4

View File

@ -0,0 +1,5 @@
<?php
class Foo {
public const BAR = NonExistent::CLASS_CONSTANT;
}

15
Zend/tests/gh7771_2.phpt Normal file
View File

@ -0,0 +1,15 @@
--TEST--
GH-7771 (Incorrect file/line for class constant expression exceptions)
--FILE--
<?php
include __DIR__ . '/gh7771_2_definition.inc';
new Foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Class "NonExistent" not found in %sgh7771_2_definition.inc:6
Stack trace:
#0 {main}
thrown in %sgh7771_2_definition.inc on line 6

View File

@ -0,0 +1,8 @@
<?php
class Foo {
public const BAR =
self::BAZ
+ NonExistent::CLASS_CONSTANT;
public const BAZ = 42;
}

View File

@ -789,7 +789,20 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
{ {
zend_string *class_name = zend_ast_get_str(ast->child[0]); zend_string *class_name = zend_ast_get_str(ast->child[0]);
zend_string *const_name = zend_ast_get_str(ast->child[1]); zend_string *const_name = zend_ast_get_str(ast->child[1]);
zend_string *previous_filename;
zend_long previous_lineno;
if (scope) {
previous_filename = EG(filename_override);
previous_lineno = EG(lineno_override);
EG(filename_override) = scope->info.user.filename;
EG(lineno_override) = zend_ast_get_lineno(ast);
}
zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr); zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
if (scope) {
EG(filename_override) = previous_filename;
EG(lineno_override) = previous_lineno;
}
if (UNEXPECTED(zv == NULL)) { if (UNEXPECTED(zv == NULL)) {
ZVAL_UNDEF(result); ZVAL_UNDEF(result);
@ -951,6 +964,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
zend_ast *new = (zend_ast*)buf; zend_ast *new = (zend_ast*)buf;
new->kind = ast->kind; new->kind = ast->kind;
new->attr = ast->attr; new->attr = ast->attr;
new->lineno = ast->lineno;
buf = (void*)((char*)buf + zend_ast_size(children)); buf = (void*)((char*)buf + zend_ast_size(children));
for (i = 0; i < children; i++) { for (i = 0; i < children; i++) {
if (ast->child[i]) { if (ast->child[i]) {

View File

@ -192,6 +192,9 @@ void init_executor(void) /* {{{ */
EG(num_errors) = 0; EG(num_errors) = 0;
EG(errors) = NULL; EG(errors) = NULL;
EG(filename_override) = NULL;
EG(lineno_override) = -1;
zend_fiber_init(); zend_fiber_init();
zend_weakrefs_init(); zend_weakrefs_init();
@ -462,6 +465,8 @@ void shutdown_executor(void) /* {{{ */
if (EG(ht_iterators) != EG(ht_iterators_slots)) { if (EG(ht_iterators) != EG(ht_iterators_slots)) {
efree(EG(ht_iterators)); efree(EG(ht_iterators));
} }
ZEND_ASSERT(EG(filename_override) == NULL);
} }
#if ZEND_DEBUG #if ZEND_DEBUG
@ -591,21 +596,18 @@ ZEND_API const char *get_function_arg_name(const zend_function *func, uint32_t a
ZEND_API const char *zend_get_executed_filename(void) /* {{{ */ ZEND_API const char *zend_get_executed_filename(void) /* {{{ */
{ {
zend_execute_data *ex = EG(current_execute_data); zend_string *filename = zend_get_executed_filename_ex();
return filename != NULL ? ZSTR_VAL(filename) : "[no active file]";
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
ex = ex->prev_execute_data;
}
if (ex) {
return ZSTR_VAL(ex->func->op_array.filename);
} else {
return "[no active file]";
}
} }
/* }}} */ /* }}} */
ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */ ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
{ {
zend_string *filename_override = EG(filename_override);
if (filename_override != NULL) {
return filename_override;
}
zend_execute_data *ex = EG(current_execute_data); zend_execute_data *ex = EG(current_execute_data);
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {
@ -621,6 +623,11 @@ ZEND_API zend_string *zend_get_executed_filename_ex(void) /* {{{ */
ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */ ZEND_API uint32_t zend_get_executed_lineno(void) /* {{{ */
{ {
zend_long lineno_override = EG(lineno_override);
if (lineno_override != -1) {
return lineno_override;
}
zend_execute_data *ex = EG(current_execute_data); zend_execute_data *ex = EG(current_execute_data);
while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) {

View File

@ -266,6 +266,10 @@ struct _zend_executor_globals {
uint32_t num_errors; uint32_t num_errors;
zend_error_info **errors; zend_error_info **errors;
/* Override filename or line number of thrown errors and exceptions */
zend_string *filename_override;
zend_long lineno_override;
void *reserved[ZEND_MAX_RESERVED_RESOURCES]; void *reserved[ZEND_MAX_RESERVED_RESOURCES];
}; };