Skip to content

Commit a19029f

Browse files
committed
Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed SplFileObject::__constructor)
Closes GH-16480 Closes GH-16604
1 parent 144d2ee commit a19029f

File tree

4 files changed

+52
-7
lines changed

4 files changed

+52
-7
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ PHP NEWS
103103
. Fixed bug GH-16479 (Use-after-free in SplObjectStorage::setInfo()). (ilutov)
104104
. Fixed bug GH-16478 (Use-after-free in SplFixedArray::unset()). (ilutov)
105105
. Fixed bug GH-16588 (UAF in Observer->serialize). (nielsdos)
106+
. Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed
107+
SplFileObject::__constructor). (Girgias)
106108

107109
- Standard:
108110
. Fixed bug GH-16293 (Failed assertion when throwing in assert() callback with

ext/spl/spl_directory.c

+12-7
Original file line numberDiff line numberDiff line change
@@ -2042,22 +2042,21 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i
20422042
PHP_METHOD(SplFileObject, __construct)
20432043
{
20442044
spl_filesystem_object *intern = spl_filesystem_from_obj(Z_OBJ_P(ZEND_THIS));
2045+
zend_string *file_name = NULL;
20452046
zend_string *open_mode = ZSTR_CHAR('r');
2047+
zval *stream_context = NULL;
20462048
bool use_include_path = 0;
20472049
size_t path_len;
20482050
zend_error_handling error_handling;
20492051

2050-
intern->u.file.open_mode = ZSTR_CHAR('r');
2051-
2052-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|Sbr!",
2053-
&intern->file_name, &open_mode,
2054-
&use_include_path, &intern->u.file.zcontext) == FAILURE) {
2055-
intern->u.file.open_mode = NULL;
2056-
intern->file_name = NULL;
2052+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|Sbr!", &file_name, &open_mode, &use_include_path, &stream_context) == FAILURE) {
20572053
RETURN_THROWS();
20582054
}
20592055

20602056
intern->u.file.open_mode = zend_string_copy(open_mode);
2057+
/* file_name and zcontext are copied by spl_filesystem_file_open() */
2058+
intern->file_name = file_name;
2059+
intern->u.file.zcontext = stream_context;
20612060

20622061
/* spl_filesystem_file_open() can generate E_WARNINGs which we want to promote to exceptions */
20632062
zend_replace_error_handling(EH_THROW, spl_ce_RuntimeException, &error_handling);
@@ -2096,6 +2095,12 @@ PHP_METHOD(SplTempFileObject, __construct)
20962095
RETURN_THROWS();
20972096
}
20982097

2098+
/* Prevent reinitialization of Object */
2099+
if (intern->u.file.stream) {
2100+
zend_throw_error(NULL, "Cannot call constructor twice");
2101+
RETURN_THROWS();
2102+
}
2103+
20992104
if (max_memory < 0) {
21002105
file_name = zend_string_init("php://memory", sizeof("php://memory")-1, 0);
21012106
} else if (ZEND_NUM_ARGS()) {

ext/spl/tests/gh16477-2.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-16477-2: Memory leak when calling SplTempFileObject::__constructor() twice
3+
--FILE--
4+
<?php
5+
6+
$obj = new SplTempFileObject();
7+
8+
try {
9+
$obj->__construct();
10+
} catch (Throwable $e) {
11+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
12+
}
13+
$obj->__debugInfo();
14+
15+
?>
16+
DONE
17+
--EXPECT--
18+
Error: Cannot call constructor twice
19+
DONE

ext/spl/tests/gh16477.phpt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
GH-16477: Segmentation fault when calling __debugInfo() after failed SplFileObject::__constructor
3+
--FILE--
4+
<?php
5+
6+
$obj = new SplFileObject(__FILE__);
7+
8+
try {
9+
$obj->__construct();
10+
} catch (Throwable $e) {
11+
echo $e::class, ': ', $e->getMessage(), PHP_EOL;
12+
}
13+
$obj->__debugInfo();
14+
15+
?>
16+
DONE
17+
--EXPECT--
18+
ArgumentCountError: SplFileObject::__construct() expects at least 1 argument, 0 given
19+
DONE

0 commit comments

Comments
 (0)