diff --git a/Zend/tests/bug41633_2.phpt b/Zend/tests/bug41633_2.phpt index 975d2218b55e3..bb768c0e11743 100644 --- a/Zend/tests/bug41633_2.phpt +++ b/Zend/tests/bug41633_2.phpt @@ -11,4 +11,4 @@ echo Foo::A."\n"; Fatal error: Uncaught Error: Undefined constant self::B in %s:%d Stack trace: #0 {main} - thrown in %sbug41633_2.php on line 5 + thrown in %sbug41633_2.php on line 3 diff --git a/Zend/tests/gh7771_1.phpt b/Zend/tests/gh7771_1.phpt new file mode 100644 index 0000000000000..dc24b4041c716 --- /dev/null +++ b/Zend/tests/gh7771_1.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-7771 (Incorrect file/line for class constant expression exceptions) +--FILE-- + +--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 diff --git a/Zend/tests/gh7771_1_definition.inc b/Zend/tests/gh7771_1_definition.inc new file mode 100644 index 0000000000000..16e94f41a0fa4 --- /dev/null +++ b/Zend/tests/gh7771_1_definition.inc @@ -0,0 +1,5 @@ + +--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 diff --git a/Zend/tests/gh7771_2_definition.inc b/Zend/tests/gh7771_2_definition.inc new file mode 100644 index 0000000000000..0162a9c8bf1ed --- /dev/null +++ b/Zend/tests/gh7771_2_definition.inc @@ -0,0 +1,8 @@ +child[0]); 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); + if (scope) { + EG(filename_override) = previous_filename; + EG(lineno_override) = previous_lineno; + } if (UNEXPECTED(zv == NULL)) { 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; new->kind = ast->kind; new->attr = ast->attr; + new->lineno = ast->lineno; buf = (void*)((char*)buf + zend_ast_size(children)); for (i = 0; i < children; i++) { if (ast->child[i]) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index fed3ae1d29963..216556b9310f3 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -192,6 +192,9 @@ void init_executor(void) /* {{{ */ EG(num_errors) = 0; EG(errors) = NULL; + EG(filename_override) = NULL; + EG(lineno_override) = -1; + zend_fiber_init(); zend_weakrefs_init(); @@ -450,6 +453,8 @@ void shutdown_executor(void) /* {{{ */ if (EG(ht_iterators) != EG(ht_iterators_slots)) { efree(EG(ht_iterators)); } + + ZEND_ASSERT(EG(filename_override) == NULL); } #if ZEND_DEBUG @@ -579,21 +584,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_execute_data *ex = EG(current_execute_data); - - 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_string *filename = zend_get_executed_filename_ex(); + return filename != NULL ? ZSTR_VAL(filename) : "[no active file]"; } /* }}} */ 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); while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { @@ -609,6 +611,11 @@ ZEND_API zend_string *zend_get_executed_filename_ex(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); while (ex && (!ex->func || !ZEND_USER_CODE(ex->func->type))) { diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 1726dee9ac12a..ccee57b3fb1bd 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -266,6 +266,10 @@ struct _zend_executor_globals { uint32_t num_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]; };