From 97a90f43617badc7b917d51f6138a7387ab03a46 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 13 Dec 2025 10:20:58 +0000 Subject: [PATCH] Fix GH-20678: resource created by GlobIterator crashes with fclose(). close GH-20697 --- NEWS | 4 ++++ ext/spl/spl_directory.c | 5 +++++ ext/spl/tests/gh20678.phpt | 14 ++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 ext/spl/tests/gh20678.phpt diff --git a/NEWS b/NEWS index 007faa02495..ed2c4149a03 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,10 @@ PHP NEWS - LDAP: . Fix memory leak in ldap_set_options(). (ndossche) +- SPL: + . Fixed bug GH-20678 (resource created by GlobIterator crashes with fclose()). + (David Carlier) + - Standard: . Fix error check for proc_open() command. (ndossche) diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 0a4d1456d65..16bb6a11e52 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -306,6 +306,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 00000000000..243f8cef06d --- /dev/null +++ b/ext/spl/tests/gh20678.phpt @@ -0,0 +1,14 @@ +--TEST-- +GH-20678 (resource created by GlobalIterator crashes when it is called with fclose()) +--CREDITS-- +chongwick +--FILE-- + +--EXPECTF-- + +Warning: fclose(): %d is not a valid stream resource in %s on line %d