diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index ad6fc54aeb3e..6a5fc1757f26 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -292,6 +292,11 @@ static void spl_filesystem_dir_open(spl_filesystem_object* intern, zend_string * intern->type = SPL_FS_DIR; intern->u.dir.dirp = php_stream_opendir(ZSTR_VAL(path), REPORT_ERRORS, FG(default_context)); + if (intern->u.dir.dirp) { + /* we prevent potential UAF with conflicting explicit fclose(), relying on the object destructor for this */ + intern->u.dir.dirp->flags |= PHP_STREAM_FLAG_NO_FCLOSE; + } + if (ZSTR_LEN(path) > 1 && IS_SLASH_AT(ZSTR_VAL(path), ZSTR_LEN(path)-1)) { intern->path = zend_string_init(ZSTR_VAL(path), ZSTR_LEN(path)-1, 0); } else { diff --git a/ext/spl/tests/gh20678.phpt b/ext/spl/tests/gh20678.phpt new file mode 100644 index 000000000000..00364db7f804 --- /dev/null +++ b/ext/spl/tests/gh20678.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-20678 (resource created by GlobalIterator crashes when it is called with fclose()) +--CREDITS-- +chongwick +--FILE-- + +--EXPECTF-- +Warning: fclose(): cannot close the provided stream, as it must not be manually closed in %s on line %d