mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Fix lineno for all constant expressions
Fixes GH-8821 Closes GH-8855
This commit is contained in:
parent
c8cc355070
commit
9e097822e8
17 changed files with 111 additions and 12 deletions
2
NEWS
2
NEWS
|
@ -20,6 +20,8 @@ PHP NEWS
|
|||
effects). (ilutov)
|
||||
. Implement GH-10217 (Use strlen() for determining the class_name length).
|
||||
(Dennis Buteyn)
|
||||
. Fix bug GH-8821 (Improve line numbers for errors in constant expressions).
|
||||
(ilutov)
|
||||
|
||||
- Exif:
|
||||
. Removed unneeded codepaths in exif_process_TIFF_in_JPEG(). (nielsdos)
|
||||
|
|
|
@ -10,5 +10,6 @@ echo Foo::A."\n";
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Undefined constant self::B in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sbug41633_2.php on line 3
|
||||
|
|
|
@ -11,5 +11,6 @@ echo Foo::A;
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Cannot declare self-referencing constant Foo::B in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sbug41633_3.php on line %d
|
||||
|
|
|
@ -16,5 +16,6 @@ $foo = new Foo();
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Undefined constant "FOO" in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
|
@ -21,5 +21,6 @@ var_dump((new C)->options);
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Undefined constant I::FOO in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sbug74657.php on line %d
|
||||
|
|
|
@ -11,5 +11,6 @@ var_dump(A::FOO);
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Cannot declare self-referencing constant self::BAR in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
|
@ -25,5 +25,6 @@ var_dump(X::FOO_BAR);
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Cannot use [] on objects in constant expression in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
|
@ -11,5 +11,6 @@ new Foo();
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Class "NonExistent" not found in %sgh7771_1_definition.inc:4
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %sgh7771_1.php(5): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sgh7771_1_definition.inc on line 4
|
||||
|
|
|
@ -11,5 +11,6 @@ new Foo();
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Class "NonExistent" not found in %sgh7771_2_definition.inc:6
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %sgh7771_2.php(5): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sgh7771_2_definition.inc on line 6
|
||||
|
|
22
Zend/tests/gh8821.phpt
Normal file
22
Zend/tests/gh8821.phpt
Normal file
|
@ -0,0 +1,22 @@
|
|||
--TEST--
|
||||
GH-8821: Fix reported line number of constant expression
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
enum Alpha {
|
||||
case Foo;
|
||||
}
|
||||
|
||||
class Bravo {
|
||||
public const C = [Alpha::Foo => 3];
|
||||
}
|
||||
|
||||
new Bravo();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught TypeError: Illegal offset type in %sgh8821.php:8
|
||||
Stack trace:
|
||||
#0 %sgh8821.php(11): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %sgh8821.php on line 8
|
|
@ -11,5 +11,6 @@ $foo = new Foo();
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Class "BAR" not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
|
@ -496,12 +496,43 @@ zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
|
|||
return zend_fetch_class_with_scope(zend_ast_get_str(ast), (ast->attr >> ZEND_CONST_EXPR_NEW_FETCH_TYPE_SHIFT) | ZEND_FETCH_CLASS_EXCEPTION, scope);
|
||||
}
|
||||
|
||||
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
zval *result,
|
||||
zend_ast *ast,
|
||||
zend_class_entry *scope,
|
||||
bool *short_circuited_ptr,
|
||||
zend_ast_evaluate_ctx *ctx
|
||||
);
|
||||
|
||||
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(
|
||||
zval *result,
|
||||
zend_ast *ast,
|
||||
zend_class_entry *scope,
|
||||
bool *short_circuited_ptr,
|
||||
zend_ast_evaluate_ctx *ctx
|
||||
) {
|
||||
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);
|
||||
}
|
||||
zend_result r = zend_ast_evaluate_inner(result, ast, scope, short_circuited_ptr, ctx);
|
||||
if (scope) {
|
||||
EG(filename_override) = previous_filename;
|
||||
EG(lineno_override) = previous_lineno;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
|
||||
zval *result,
|
||||
zend_ast *ast,
|
||||
zend_class_entry *scope,
|
||||
bool *short_circuited_ptr,
|
||||
zend_ast_evaluate_ctx *ctx
|
||||
) {
|
||||
zval op1, op2;
|
||||
zend_result ret = SUCCESS;
|
||||
|
@ -1023,11 +1054,13 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
|
|||
new->attr = ast->attr;
|
||||
ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
|
||||
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
|
||||
// Lineno gets copied with ZVAL_COPY
|
||||
} else if (ast->kind == ZEND_AST_CONSTANT) {
|
||||
zend_ast_zval *new = (zend_ast_zval*)buf;
|
||||
new->kind = ZEND_AST_CONSTANT;
|
||||
new->attr = ast->attr;
|
||||
ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
|
||||
Z_LINENO(new->val) = zend_ast_get_lineno(ast);
|
||||
buf = (void*)((char*)buf + sizeof(zend_ast_zval));
|
||||
} else if (zend_ast_is_list(ast)) {
|
||||
zend_ast_list *list = zend_ast_get_list(ast);
|
||||
|
@ -1036,6 +1069,7 @@ static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
|
|||
new->kind = list->kind;
|
||||
new->attr = list->attr;
|
||||
new->children = list->children;
|
||||
new->lineno = list->lineno;
|
||||
buf = (void*)((char*)buf + zend_ast_list_size(list->children));
|
||||
for (i = 0; i < list->children; i++) {
|
||||
if (list->child[i]) {
|
||||
|
|
|
@ -352,6 +352,9 @@ static zend_always_inline uint32_t zend_ast_get_lineno(zend_ast *ast) {
|
|||
if (ast->kind == ZEND_AST_ZVAL) {
|
||||
zval *zv = zend_ast_get_zval(ast);
|
||||
return Z_LINENO_P(zv);
|
||||
} else if (ast->kind == ZEND_AST_CONSTANT) {
|
||||
zval *zv = &((zend_ast_zval *) ast)->val;
|
||||
return Z_LINENO_P(zv);
|
||||
} else {
|
||||
return ast->lineno;
|
||||
}
|
||||
|
|
|
@ -1724,6 +1724,32 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
|
|||
return;
|
||||
}
|
||||
|
||||
if (EG(filename_override)) {
|
||||
// Add the current execution point to the frame so we don't lose it
|
||||
zend_string *filename_override = EG(filename_override);
|
||||
zend_long lineno_override = EG(lineno_override);
|
||||
EG(filename_override) = NULL;
|
||||
EG(lineno_override) = -1;
|
||||
|
||||
zend_string *filename = zend_get_executed_filename_ex();
|
||||
zend_long lineno = zend_get_executed_lineno();
|
||||
if (filename && (!zend_string_equals(filename, filename_override) || lineno != lineno_override)) {
|
||||
stack_frame = zend_new_array(8);
|
||||
zend_hash_real_init_mixed(stack_frame);
|
||||
ZVAL_STR_COPY(&tmp, filename);
|
||||
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FILE), &tmp, 1);
|
||||
ZVAL_LONG(&tmp, lineno);
|
||||
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_LINE), &tmp, 1);
|
||||
ZVAL_STR_COPY(&tmp, ZSTR_KNOWN(ZEND_STR_CONST_EXPR_PLACEHOLDER));
|
||||
_zend_hash_append_ex(stack_frame, ZSTR_KNOWN(ZEND_STR_FUNCTION), &tmp, 1);
|
||||
ZVAL_ARR(&tmp, stack_frame);
|
||||
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
|
||||
}
|
||||
|
||||
EG(filename_override) = filename_override;
|
||||
EG(lineno_override) = lineno_override;
|
||||
}
|
||||
|
||||
if (skip_last) {
|
||||
/* skip debug_backtrace() */
|
||||
call = call->prev_execute_data;
|
||||
|
|
|
@ -594,6 +594,7 @@ EMPTY_SWITCH_DEFAULT_CASE()
|
|||
_(ZEND_STR_AUTOGLOBAL_REQUEST, "_REQUEST") \
|
||||
_(ZEND_STR_COUNT, "count") \
|
||||
_(ZEND_STR_SENSITIVEPARAMETER, "SensitiveParameter") \
|
||||
_(ZEND_STR_CONST_EXPR_PLACEHOLDER, "[constant expression]") \
|
||||
|
||||
|
||||
typedef enum _zend_known_string_id {
|
||||
|
|
|
@ -12,6 +12,7 @@ file_get_contents('error://test');
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Undefined constant self::INVALID in %s:%d
|
||||
Stack trace:
|
||||
#0 %sbug77664.php(%d): file_get_contents('error://test')
|
||||
#1 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 %s(%d): file_get_contents('error://test')
|
||||
#2 {main}
|
||||
thrown in %sbug77664.php on line %d
|
||||
|
|
|
@ -12,5 +12,6 @@ Class constant whose initial value references a non-existent class
|
|||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Class "D" not found in %s:%d
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
#0 %s(%d): [constant expression]()
|
||||
#1 {main}
|
||||
thrown in %s on line %d
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue