Skip to content

Commit ba3c529

Browse files
committed
Adjust filename/lineno for constant expressions
Closes GH-7771 Closes GH-8124
1 parent 51f750e commit ba3c529

9 files changed

+78
-1
lines changed

Zend/tests/bug41633_2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ echo Foo::A."\n";
1111
Fatal error: Uncaught Error: Undefined constant self::B in %s:%d
1212
Stack trace:
1313
#0 {main}
14-
thrown in %sbug41633_2.php on line 5
14+
thrown in %sbug41633_2.php on line 3

Zend/tests/gh7771_1.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
GH-7771 (Incorrect file/line for class constant expression exceptions)
3+
--FILE--
4+
<?php
5+
6+
include __DIR__ . '/gh7771_1_definition.inc';
7+
8+
new Foo();
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Uncaught Error: Class "NonExistent" not found in %s/Zend/tests/gh7771_1_definition.inc:4
13+
Stack trace:
14+
#0 {main}
15+
thrown in %s/Zend/tests/gh7771_1_definition.inc on line 4

Zend/tests/gh7771_1_definition.inc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
class Foo {
4+
public const BAR = NonExistent::CLASS_CONSTANT;
5+
}

Zend/tests/gh7771_2.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
GH-7771 (Incorrect file/line for class constant expression exceptions)
3+
--FILE--
4+
<?php
5+
6+
include __DIR__ . '/gh7771_2_definition.inc';
7+
8+
new Foo();
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Uncaught Error: Class "NonExistent" not found in %s/Zend/tests/gh7771_2_definition.inc:6
13+
Stack trace:
14+
#0 {main}
15+
thrown in %s/Zend/tests/gh7771_2_definition.inc on line 6

Zend/tests/gh7771_2_definition.inc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
class Foo {
4+
public const BAR =
5+
self::BAZ
6+
+ NonExistent::CLASS_CONSTANT;
7+
public const BAZ = 42;
8+
}

Zend/zend_ast.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,20 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
789789
{
790790
zend_string *class_name = zend_ast_get_str(ast->child[0]);
791791
zend_string *const_name = zend_ast_get_str(ast->child[1]);
792+
793+
zend_string *previous_filename;
794+
zend_long previous_lineno;
795+
if (scope) {
796+
previous_filename = EG(exception_filename);
797+
previous_lineno = EG(exception_lineno);
798+
EG(exception_filename) = scope->info.user.filename;
799+
EG(exception_lineno) = zend_ast_get_lineno(ast);
800+
}
792801
zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
802+
if (scope) {
803+
EG(exception_filename) = previous_filename;
804+
EG(exception_lineno) = previous_lineno;
805+
}
793806

794807
if (UNEXPECTED(zv == NULL)) {
795808
ZVAL_UNDEF(result);
@@ -951,6 +964,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
951964
zend_ast *new = (zend_ast*)buf;
952965
new->kind = ast->kind;
953966
new->attr = ast->attr;
967+
new->lineno = ast->lineno;
954968
buf = (void*)((char*)buf + zend_ast_size(children));
955969
for (i = 0; i < children; i++) {
956970
if (ast->child[i]) {

Zend/zend_exceptions.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,17 @@ static zend_object *zend_throw_exception_zstr(zend_class_entry *exception_ce, ze
822822
zend_update_property_ex(exception_ce, Z_OBJ(ex), ZSTR_KNOWN(ZEND_STR_CODE), &tmp);
823823
}
824824

825+
zend_string *exception_filename = EG(exception_filename);
826+
if (exception_filename != NULL) {
827+
ZVAL_STR(&tmp, exception_filename);
828+
zend_update_property_ex(exception_ce, Z_OBJ(ex), ZSTR_KNOWN(ZEND_STR_FILE), &tmp);
829+
830+
zend_long exception_filename = EG(exception_lineno);
831+
ZEND_ASSERT(exception_filename != -1);
832+
ZVAL_LONG(&tmp, exception_filename);
833+
zend_update_property_ex(exception_ce, Z_OBJ(ex), ZSTR_KNOWN(ZEND_STR_LINE), &tmp);
834+
}
835+
825836
zend_throw_exception_internal(Z_OBJ(ex));
826837

827838
return Z_OBJ(ex);

Zend/zend_execute_API.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ void init_executor(void) /* {{{ */
192192
EG(num_errors) = 0;
193193
EG(errors) = NULL;
194194

195+
EG(exception_filename) = NULL;
196+
EG(exception_lineno) = -1;
197+
195198
zend_fiber_init();
196199
zend_weakrefs_init();
197200

@@ -450,6 +453,8 @@ void shutdown_executor(void) /* {{{ */
450453
if (EG(ht_iterators) != EG(ht_iterators_slots)) {
451454
efree(EG(ht_iterators));
452455
}
456+
457+
ZEND_ASSERT(EG(exception_filename) == NULL);
453458
}
454459

455460
#if ZEND_DEBUG

Zend/zend_globals.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ struct _zend_executor_globals {
266266
uint32_t num_errors;
267267
zend_error_info **errors;
268268

269+
/* Overwrite filename or line number of thrown exceptions */
270+
zend_string *exception_filename;
271+
zend_long exception_lineno;
272+
269273
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
270274
};
271275

0 commit comments

Comments
 (0)