Skip to content

Commit 44cd74b

Browse files
committed
Fix lineno in backtrace of multi-line function calls
Closes GH-8810 Closes GH-8818
1 parent 7cd8879 commit 44cd74b

File tree

11 files changed

+168
-19
lines changed

11 files changed

+168
-19
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ PHP NEWS
1111
warning). (ilutov)
1212
. Fixed bug GH-7821 and GH-8418 (Allow arbitrary const expressions in backed
1313
enums). (ilutov)
14+
. Fixed bug GH-8810 (Incorrect lineno in backtrace of multi-line function
15+
calls). (ilutov)
1416

1517
- Curl:
1618
. Added new constants from cURL 7.62 to 7.80. (Pierrick)

Zend/tests/gh8810_1.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line function call
3+
--FILE--
4+
<?php
5+
6+
function foo($bar, $baz) {
7+
throw new Exception();
8+
}
9+
10+
foo
11+
(
12+
'bar',
13+
'baz',
14+
);
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Exception in %s:4
19+
Stack trace:
20+
#0 %s(7): foo('bar', 'baz')
21+
#1 {main}
22+
thrown in %s on line 4

Zend/tests/gh8810_2.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line method call
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public function b() {
8+
throw new Exception();
9+
}
10+
}
11+
12+
(new A())
13+
->
14+
b
15+
();
16+
17+
?>
18+
--EXPECTF--
19+
Fatal error: Uncaught Exception in %s:5
20+
Stack trace:
21+
#0 %s(11): A->b()
22+
#1 {main}
23+
thrown in %s on line 5

Zend/tests/gh8810_3.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line closure call
3+
--FILE--
4+
<?php
5+
6+
(function () {
7+
throw new Exception();
8+
})
9+
(
10+
'foo',
11+
);
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught Exception in %s:4
16+
Stack trace:
17+
#0 %s(6): {closure}('foo')
18+
#1 {main}
19+
thrown in %s on line 4

Zend/tests/gh8810_4.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line dynamic call
3+
--FILE--
4+
<?php
5+
6+
function foo() {
7+
throw new Exception();
8+
}
9+
10+
'foo'
11+
();
12+
13+
?>
14+
--EXPECTF--
15+
Fatal error: Uncaught Exception in %s:4
16+
Stack trace:
17+
#0 %s(8): foo()
18+
#1 {main}
19+
thrown in %s on line 4

Zend/tests/gh8810_5.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line assert call
3+
--FILE--
4+
<?php
5+
6+
assert(
7+
false,
8+
);
9+
10+
?>
11+
--EXPECTF--
12+
Fatal error: Uncaught AssertionError: assert(false) in %s:3
13+
Stack trace:
14+
#0 %s(3): assert(false, 'assert(false)')
15+
#1 {main}
16+
thrown in %s on line 3

Zend/tests/gh8810_6.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line static call
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public static function b() {
8+
throw new Exception();
9+
}
10+
}
11+
12+
A
13+
::
14+
b
15+
();
16+
17+
?>
18+
--EXPECTF--
19+
Fatal error: Uncaught Exception in %s:5
20+
Stack trace:
21+
#0 %s(11): A::b()
22+
#1 {main}
23+
thrown in %s on line 5

Zend/tests/gh8810_7.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
GH-8810: Fix reported line number of multi-line new call
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public function __construct() {
8+
throw new Exception();
9+
}
10+
}
11+
12+
new
13+
A
14+
();
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Uncaught Exception in %s:5
19+
Stack trace:
20+
#0 %s(10): A->__construct()
21+
#1 {main}
22+
thrown in %s on line 5

Zend/zend_compile.c

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,7 +3623,7 @@ ZEND_API zend_uchar zend_get_call_op(const zend_op *init_op, zend_function *fbc)
36233623
}
36243624
/* }}} */
36253625

3626-
static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc) /* {{{ */
3626+
static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_function *fbc, uint32_t lineno) /* {{{ */
36273627
{
36283628
zend_op *opline;
36293629
uint32_t opnum_init = get_next_op_number() - 1;
@@ -3660,6 +3660,7 @@ static bool zend_compile_call_common(znode *result, zend_ast *args_ast, zend_fun
36603660
if (may_have_extra_named_args) {
36613661
opline->extended_value = ZEND_FCALL_MAY_HAVE_EXTRA_NAMED_PARAMS;
36623662
}
3663+
opline->lineno = lineno;
36633664
zend_do_extended_fcall_end();
36643665
return false;
36653666
}
@@ -3678,7 +3679,7 @@ static bool zend_compile_function_name(znode *name_node, zend_ast *name_ast) /*
36783679
}
36793680
/* }}} */
36803681

3681-
static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3682+
static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */
36823683
{
36833684
zend_op *opline = get_next_op();
36843685
opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME;
@@ -3687,11 +3688,11 @@ static void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args
36873688
Z_STR(name_node->u.constant));
36883689
opline->result.num = zend_alloc_cache_slot();
36893690

3690-
zend_compile_call_common(result, args_ast, NULL);
3691+
zend_compile_call_common(result, args_ast, NULL, lineno);
36913692
}
36923693
/* }}} */
36933694

3694-
static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
3695+
static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast, uint32_t lineno) /* {{{ */
36953696
{
36963697
if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
36973698
const char *colon;
@@ -3721,7 +3722,7 @@ static void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast
37213722
zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
37223723
}
37233724

3724-
zend_compile_call_common(result, args_ast, NULL);
3725+
zend_compile_call_common(result, args_ast, NULL, lineno);
37253726
}
37263727
/* }}} */
37273728

@@ -4015,7 +4016,7 @@ static zend_result zend_compile_func_cuf(znode *result, zend_ast_list *args, zen
40154016
}
40164017
/* }}} */
40174018

4018-
static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc) /* {{{ */
4019+
static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string *name, zend_function *fbc, uint32_t lineno) /* {{{ */
40194020
{
40204021
if (EG(assertions) >= 0) {
40214022
znode name_node;
@@ -4050,7 +4051,7 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string
40504051
zend_ast_list_add((zend_ast *) args, arg);
40514052
}
40524053

4053-
zend_compile_call_common(result, (zend_ast*)args, fbc);
4054+
zend_compile_call_common(result, (zend_ast*)args, fbc, lineno);
40544055

40554056
opline = &CG(active_op_array)->opcodes[check_op_number];
40564057
opline->op2.opline_num = get_next_op_number();
@@ -4377,7 +4378,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{
43774378

43784379
if (name_ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(name_ast)) != IS_STRING) {
43794380
zend_compile_expr(&name_node, name_ast);
4380-
zend_compile_dynamic_call(result, &name_node, args_ast);
4381+
zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
43814382
return;
43824383
}
43834384

@@ -4386,9 +4387,9 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{
43864387
if (runtime_resolution) {
43874388
if (zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "assert")
43884389
&& !is_callable_convert) {
4389-
zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL);
4390+
zend_compile_assert(result, zend_ast_get_list(args_ast), Z_STR(name_node.u.constant), NULL, ast->lineno);
43904391
} else {
4391-
zend_compile_ns_call(result, &name_node, args_ast);
4392+
zend_compile_ns_call(result, &name_node, args_ast, ast->lineno);
43924393
}
43934394
return;
43944395
}
@@ -4405,7 +4406,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{
44054406

44064407
/* Special assert() handling should apply independently of compiler flags. */
44074408
if (fbc && zend_string_equals_literal(lcname, "assert") && !is_callable_convert) {
4408-
zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc);
4409+
zend_compile_assert(result, zend_ast_get_list(args_ast), lcname, fbc, ast->lineno);
44094410
zend_string_release(lcname);
44104411
zval_ptr_dtor(&name_node.u.constant);
44114412
return;
@@ -4417,7 +4418,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{
44174418
|| (fbc->type == ZEND_USER_FUNCTION && (CG(compiler_options) & ZEND_COMPILE_IGNORE_OTHER_FILES) && fbc->op_array.filename != CG(active_op_array)->filename)
44184419
) {
44194420
zend_string_release_ex(lcname, 0);
4420-
zend_compile_dynamic_call(result, &name_node, args_ast);
4421+
zend_compile_dynamic_call(result, &name_node, args_ast, ast->lineno);
44214422
return;
44224423
}
44234424

@@ -4436,7 +4437,7 @@ static void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{
44364437
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
44374438
opline->result.num = zend_alloc_cache_slot();
44384439

4439-
zend_compile_call_common(result, args_ast, fbc);
4440+
zend_compile_call_common(result, args_ast, fbc, ast->lineno);
44404441
}
44414442
}
44424443
/* }}} */
@@ -4500,7 +4501,7 @@ static void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type
45004501
}
45014502
}
45024503

4503-
if (zend_compile_call_common(result, args_ast, fbc)) {
4504+
if (zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast))) {
45044505
if (short_circuiting_checkpoint != zend_short_circuiting_checkpoint()) {
45054506
zend_error_noreturn(E_COMPILE_ERROR,
45064507
"Cannot combine nullsafe operator with Closure creation");
@@ -4597,7 +4598,7 @@ static void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type
45974598
}
45984599
}
45994600

4600-
zend_compile_call_common(result, args_ast, fbc);
4601+
zend_compile_call_common(result, args_ast, fbc, zend_ast_get_lineno(method_ast));
46014602
}
46024603
/* }}} */
46034604

@@ -4629,7 +4630,7 @@ static void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
46294630
SET_NODE(opline->op1, &class_node);
46304631
}
46314632

4632-
zend_compile_call_common(&ctor_result, args_ast, NULL);
4633+
zend_compile_call_common(&ctor_result, args_ast, NULL, ast->lineno);
46334634
zend_do_free(&ctor_result);
46344635
}
46354636
/* }}} */

Zend/zend_language_parser.y

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,8 +1263,10 @@ function_call:
12631263
{ $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
12641264
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name argument_list
12651265
{ $$ = zend_ast_create(ZEND_AST_STATIC_CALL, $1, $3, $4); }
1266-
| callable_expr argument_list
1267-
{ $$ = zend_ast_create(ZEND_AST_CALL, $1, $2); }
1266+
| callable_expr { $<num>$ = CG(zend_lineno); } argument_list {
1267+
$$ = zend_ast_create(ZEND_AST_CALL, $1, $3);
1268+
$$->lineno = $<num>2;
1269+
}
12681270
;
12691271

12701272
class_name:

ext/intl/tests/dateformat_calendars_variant3.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12"
4141
string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12"
4242
string(44) "Sunday, 6 Tevet 5772 at 5:12:00 AM GMT+05:12"
4343

44-
Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:27
44+
Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:%d
4545
Stack trace:
4646
#0 %sdateformat_calendars_variant3.php(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1)
4747
#1 {main}

0 commit comments

Comments
 (0)