Skip to content

Commit 32f377b

Browse files
committed
Fixed bug #79710
Make sure we don't use zresource after the stream has been destroyed.
1 parent 5621c5f commit 32f377b

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ PHP NEWS
2626
. Fixed bug #79664 (PDOStatement::getColumnMeta fails on empty result set).
2727
(cmb)
2828

29+
- SPL:
30+
. Fixed bug #79710 (Reproducible segfault in error_handler during GC
31+
involved an SplFileObject). (Nikita)
32+
2933
- Standard:
3034
. Fixed bug #74267 (segfault with streams and invalid data). (cmb)
3135

ext/spl/spl_directory.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */
9696
php_stream_pclose(intern->u.file.stream);
9797
}
9898
intern->u.file.stream = NULL;
99+
ZVAL_UNDEF(&intern->u.file.zresource);
99100
}
100101
break;
101102
default:
@@ -2062,12 +2063,16 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function
20622063
{
20632064
zend_fcall_info fci;
20642065
zend_fcall_info_cache fcic;
2065-
zval *zresource_ptr = &intern->u.file.zresource, retval;
2066+
zval *zresource_ptr = &intern->u.file.zresource, *params, retval;
20662067
int result;
20672068
int num_args = pass_num_args + (arg2 ? 2 : 1);
20682069

2069-
zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0);
2070+
if (Z_ISUNDEF_P(zresource_ptr)) {
2071+
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized");
2072+
return FAILURE;
2073+
}
20702074

2075+
params = (zval*)safe_emalloc(num_args, sizeof(zval), 0);
20712076
params[0] = *zresource_ptr;
20722077

20732078
if (arg2) {

ext/spl/tests/bug79710.phpt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Bug #79710: Reproducible segfault in error_handler during GC involved an SplFileObject
3+
--FILE--
4+
<?php
5+
6+
class Target
7+
{
8+
public $sfo;
9+
public function __construct($sfo) {
10+
$this->sfo = $sfo;
11+
}
12+
public function __destruct() {
13+
// If the SplFileObject is destructed first,
14+
// underlying FD is no longer valid and will cause error upon calling flock
15+
$this->sfo->flock(2);
16+
}
17+
}
18+
19+
class Run
20+
{
21+
static $sfo;
22+
static $foo;
23+
public static function main() {
24+
// Creation ordering is important for repro
25+
// $sfo needed to be destructed before $foo.
26+
Run::$sfo = new SplTempFileObject();
27+
Run::$foo = new Target(Run::$sfo);
28+
}
29+
}
30+
31+
Run::main();
32+
33+
?>
34+
--EXPECTF--
35+
Fatal error: Uncaught RuntimeException: Object not initialized in %s:%d
36+
Stack trace:
37+
#0 %s(%d): SplFileObject->flock(2)
38+
#1 [internal function]: Target->__destruct()
39+
#2 {main}
40+
thrown in %s on line %d

0 commit comments

Comments
 (0)