diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-06-19 10:46:02 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-06-19 10:46:26 +0200 |
commit | 32f377b0b94482a5b126408942646b9bd101c042 (patch) | |
tree | 70393e9c97a08b0c5971bc38c9f2a49487db9aa1 | |
parent | 5621c5faf899c94baa2b41acb457494ca30368c3 (diff) | |
download | php-git-32f377b0b94482a5b126408942646b9bd101c042.tar.gz |
Fixed bug #79710
Make sure we don't use zresource after the stream has been destroyed.
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 9 | ||||
-rw-r--r-- | ext/spl/tests/bug79710.phpt | 40 |
3 files changed, 51 insertions, 2 deletions
@@ -26,6 +26,10 @@ PHP NEWS . Fixed bug #79664 (PDOStatement::getColumnMeta fails on empty result set). (cmb) +- SPL: + . Fixed bug #79710 (Reproducible segfault in error_handler during GC + involved an SplFileObject). (Nikita) + - Standard: . Fixed bug #74267 (segfault with streams and invalid data). (cmb) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index b9e6bf91e8..6e79bc407f 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -96,6 +96,7 @@ static void spl_filesystem_object_destroy_object(zend_object *object) /* {{{ */ php_stream_pclose(intern->u.file.stream); } intern->u.file.stream = NULL; + ZVAL_UNDEF(&intern->u.file.zresource); } break; default: @@ -2062,12 +2063,16 @@ static int spl_filesystem_file_call(spl_filesystem_object *intern, zend_function { zend_fcall_info fci; zend_fcall_info_cache fcic; - zval *zresource_ptr = &intern->u.file.zresource, retval; + zval *zresource_ptr = &intern->u.file.zresource, *params, retval; int result; int num_args = pass_num_args + (arg2 ? 2 : 1); - zval *params = (zval*)safe_emalloc(num_args, sizeof(zval), 0); + if (Z_ISUNDEF_P(zresource_ptr)) { + zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Object not initialized"); + return FAILURE; + } + params = (zval*)safe_emalloc(num_args, sizeof(zval), 0); params[0] = *zresource_ptr; if (arg2) { diff --git a/ext/spl/tests/bug79710.phpt b/ext/spl/tests/bug79710.phpt new file mode 100644 index 0000000000..a5c065fd67 --- /dev/null +++ b/ext/spl/tests/bug79710.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #79710: Reproducible segfault in error_handler during GC involved an SplFileObject +--FILE-- +<?php + +class Target +{ + public $sfo; + public function __construct($sfo) { + $this->sfo = $sfo; + } + public function __destruct() { + // If the SplFileObject is destructed first, + // underlying FD is no longer valid and will cause error upon calling flock + $this->sfo->flock(2); + } +} + +class Run +{ + static $sfo; + static $foo; + public static function main() { + // Creation ordering is important for repro + // $sfo needed to be destructed before $foo. + Run::$sfo = new SplTempFileObject(); + Run::$foo = new Target(Run::$sfo); + } +} + +Run::main(); + +?> +--EXPECTF-- +Fatal error: Uncaught RuntimeException: Object not initialized in %s:%d +Stack trace: +#0 %s(%d): SplFileObject->flock(2) +#1 [internal function]: Target->__destruct() +#2 {main} + thrown in %s on line %d |