Skip to content

Commit 7eb0ac0

Browse files
committed
Fix lineno for all constant expressions
Closes GH-8821
1 parent bc03dee commit 7eb0ac0

File tree

2 files changed

+54
-23
lines changed

2 files changed

+54
-23
lines changed

Zend/tests/gh8821.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-8821: Fix reported line number of constant expression
3+
--FILE--
4+
<?php
5+
6+
enum Alpha {
7+
case Foo;
8+
}
9+
10+
class Bravo {
11+
public const C = [Alpha::Foo => 3];
12+
}
13+
14+
new Bravo();
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught TypeError: Illegal offset type in %s:8
19+
Stack trace:
20+
#0 {main}
21+
thrown in %s on line 8

Zend/zend_ast.c

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
498498
return zend_fetch_class_with_scope(zend_ast_get_str(ast), ast->attr | ZEND_FETCH_CLASS_EXCEPTION, scope);
499499
}
500500

501-
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
501+
static zend_always_inline zend_result zend_ast_evaluate_ex(zval *result, zend_ast *ast, zend_class_entry *scope)
502502
{
503503
zval op1, op2;
504504
zend_result ret = SUCCESS;
@@ -794,29 +794,8 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
794794
{
795795
zend_string *class_name = zend_ast_get_str(ast->child[0]);
796796
zend_string *const_name = zend_ast_get_str(ast->child[1]);
797-
zval *zv;
798-
bool bailout = 0;
799797

800-
zend_string *previous_filename;
801-
zend_long previous_lineno;
802-
if (scope) {
803-
previous_filename = EG(filename_override);
804-
previous_lineno = EG(lineno_override);
805-
EG(filename_override) = scope->info.user.filename;
806-
EG(lineno_override) = zend_ast_get_lineno(ast);
807-
}
808-
zend_try {
809-
zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
810-
} zend_catch {
811-
bailout = 1;
812-
} zend_end_try();
813-
if (scope) {
814-
EG(filename_override) = previous_filename;
815-
EG(lineno_override) = previous_lineno;
816-
}
817-
if (bailout) {
818-
zend_bailout();
819-
}
798+
zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
820799

821800
if (UNEXPECTED(zv == NULL)) {
822801
ZVAL_UNDEF(result);
@@ -914,6 +893,34 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast
914893
return ret;
915894
}
916895

896+
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
897+
{
898+
zend_string *previous_filename;
899+
zend_long previous_lineno;
900+
zend_result r;
901+
bool threw = false;
902+
903+
if (scope) {
904+
previous_filename = EG(filename_override);
905+
previous_lineno = EG(lineno_override);
906+
EG(filename_override) = scope->info.user.filename;
907+
EG(lineno_override) = zend_ast_get_lineno(ast);
908+
}
909+
zend_try {
910+
r = zend_ast_evaluate_ex(result, ast, scope);
911+
} zend_catch {
912+
threw = true;
913+
} zend_end_try();
914+
if (scope) {
915+
EG(filename_override) = previous_filename;
916+
EG(lineno_override) = previous_lineno;
917+
}
918+
if (threw) {
919+
zend_bailout();
920+
}
921+
return r;
922+
}
923+
917924
static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
918925
{
919926
size_t size;
@@ -950,12 +957,14 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
950957
new->kind = ZEND_AST_ZVAL;
951958
new->attr = ast->attr;
952959
ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
960+
// Lineno gets copied with ZVAL_COPY
953961
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
954962
} else if (ast->kind == ZEND_AST_CONSTANT) {
955963
zend_ast_zval *new = (zend_ast_zval*)buf;
956964
new->kind = ZEND_AST_CONSTANT;
957965
new->attr = ast->attr;
958966
ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
967+
Z_LINENO(new->val) = zend_ast_get_lineno(ast);
959968
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
960969
} else if (zend_ast_is_list(ast)) {
961970
zend_ast_list *list = zend_ast_get_list(ast);
@@ -964,6 +973,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
964973
new->kind = list->kind;
965974
new->attr = list->attr;
966975
new->children = list->children;
976+
new->lineno = list->lineno;
967977
buf = (void*)((char*)buf + zend_ast_list_size(list->children));
968978
for (i = 0; i < list->children; i++) {
969979
if (list->child[i]) {

0 commit comments

Comments
 (0)