Skip to content

Commit 8d1c0a1

Browse files
danogiluuu1994
authored andcommitted
Fix segfault when using ReflectionFiber (fixes php#10439)
Closes phpGH-10478
1 parent 939c546 commit 8d1c0a1

6 files changed

+115
-7
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ PHP NEWS
5656
- Reflection:
5757
. Fixed bug GH-10623 (Reflection::getClosureUsedVariables opcode fix with
5858
variadic arguments). (nielsdos)
59+
. Fix Segfault when using ReflectionFiber suspended by an internal function.
60+
(danog)
5961

6062
- Session:
6163
. Fixed ps_files_cleanup_dir() on failure code paths with -1 instead of 0 as

ext/reflection/php_reflection.c

+14-2
Original file line numberDiff line numberDiff line change
@@ -7017,7 +7017,13 @@ ZEND_METHOD(ReflectionFiber, getExecutingLine)
70177017
prev_execute_data = fiber->execute_data->prev_execute_data;
70187018
}
70197019

7020-
RETURN_LONG(prev_execute_data->opline->lineno);
7020+
while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) {
7021+
prev_execute_data = prev_execute_data->prev_execute_data;
7022+
}
7023+
if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
7024+
RETURN_LONG(prev_execute_data->opline->lineno);
7025+
}
7026+
RETURN_NULL();
70217027
}
70227028

70237029
ZEND_METHOD(ReflectionFiber, getExecutingFile)
@@ -7035,7 +7041,13 @@ ZEND_METHOD(ReflectionFiber, getExecutingFile)
70357041
prev_execute_data = fiber->execute_data->prev_execute_data;
70367042
}
70377043

7038-
RETURN_STR_COPY(prev_execute_data->func->op_array.filename);
7044+
while (prev_execute_data && (!prev_execute_data->func || !ZEND_USER_CODE(prev_execute_data->func->common.type))) {
7045+
prev_execute_data = prev_execute_data->prev_execute_data;
7046+
}
7047+
if (prev_execute_data && prev_execute_data->func && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
7048+
RETURN_STR_COPY(prev_execute_data->func->op_array.filename);
7049+
}
7050+
RETURN_NULL();
70397051
}
70407052

70417053
ZEND_METHOD(ReflectionFiber, getCallable)

ext/reflection/php_reflection.stub.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -756,9 +756,9 @@ public function __construct(Fiber $fiber) {}
756756

757757
public function getFiber(): Fiber {}
758758

759-
public function getExecutingFile(): string {}
759+
public function getExecutingFile(): ?string {}
760760

761-
public function getExecutingLine(): int {}
761+
public function getExecutingLine(): ?int {}
762762

763763
public function getCallable(): callable {}
764764

ext/reflection/php_reflection_arginfo.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: ab0dd21b2fc7ff18c39275e1ec82211c7058c32a */
2+
* Stub hash: 164878e6c43f0e4c8bb7a7ae1e5c9650c240d775 */
33

44
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
55
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
@@ -586,9 +586,11 @@ ZEND_END_ARG_INFO()
586586
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionFiber_getFiber, 0, 0, Fiber, 0)
587587
ZEND_END_ARG_INFO()
588588

589-
#define arginfo_class_ReflectionFiber_getExecutingFile arginfo_class_ReflectionFunction___toString
589+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getExecutingFile, 0, 0, IS_STRING, 1)
590+
ZEND_END_ARG_INFO()
590591

591-
#define arginfo_class_ReflectionFiber_getExecutingLine arginfo_class_ReflectionAttribute_getTarget
592+
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getExecutingLine, 0, 0, IS_LONG, 1)
593+
ZEND_END_ARG_INFO()
592594

593595
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_ReflectionFiber_getCallable, 0, 0, IS_CALLABLE, 0)
594596
ZEND_END_ARG_INFO()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
ReflectionFiber should not segfault when inspecting fibers with no stack frames before suspend
3+
--FILE--
4+
<?php
5+
$f = new Fiber(Fiber::suspend(...));
6+
$f->start();
7+
8+
$reflection = new ReflectionFiber($f);
9+
10+
var_dump($reflection->getExecutingFile());
11+
var_dump($reflection->getExecutingLine());
12+
var_dump($reflection->getTrace());
13+
14+
?>
15+
--EXPECTF--
16+
NULL
17+
NULL
18+
array(1) {
19+
[0]=>
20+
array(4) {
21+
["function"]=>
22+
string(7) "suspend"
23+
["class"]=>
24+
string(5) "Fiber"
25+
["type"]=>
26+
string(2) "::"
27+
["args"]=>
28+
array(0) {
29+
}
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
--TEST--
2+
ReflectionFiber should not segfault when inspecting fibers where the previous stack frame is a native function
3+
--FILE--
4+
<?php
5+
6+
namespace test;
7+
8+
$f = new \Fiber(fn() => call_user_func(["Fiber", "suspend"]));
9+
$f->start();
10+
11+
$reflection = new \ReflectionFiber($f);
12+
13+
var_dump($reflection->getExecutingFile());
14+
var_dump($reflection->getExecutingLine());
15+
var_dump($reflection->getTrace());
16+
17+
?>
18+
--EXPECTF--
19+
string(%d) "%sReflectionFiber_notrace_2.php"
20+
int(5)
21+
array(3) {
22+
[0]=>
23+
array(4) {
24+
["function"]=>
25+
string(7) "suspend"
26+
["class"]=>
27+
string(5) "Fiber"
28+
["type"]=>
29+
string(2) "::"
30+
["args"]=>
31+
array(0) {
32+
}
33+
}
34+
[1]=>
35+
array(4) {
36+
["file"]=>
37+
string(%d) "%sReflectionFiber_notrace_2.php"
38+
["line"]=>
39+
int(5)
40+
["function"]=>
41+
string(14) "call_user_func"
42+
["args"]=>
43+
array(1) {
44+
[0]=>
45+
array(2) {
46+
[0]=>
47+
string(5) "Fiber"
48+
[1]=>
49+
string(7) "suspend"
50+
}
51+
}
52+
}
53+
[2]=>
54+
array(2) {
55+
["function"]=>
56+
string(14) "test\{closure}"
57+
["args"]=>
58+
array(0) {
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)