1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Fix GH-13204: glob() fails if square bracket is in current directory (#19647)

The problem is not limited to square brackets, but to every meta
character. The solution is to override the glob functions for handling
paths with the VCWD ones in PHP. If that is not available, use the old
but limited workaround.
This commit is contained in:
Nora Dossche
2026-03-03 22:29:07 +01:00
committed by GitHub
parent f17c5ad83b
commit 84b0a73685
4 changed files with 61 additions and 9 deletions

2
NEWS
View File

@@ -123,6 +123,8 @@ PHP NEWS
defaulted to 0. (Jorg Sowa)
. Fixed bug GH-21058 (error_log() crashes with message_type 3 and
null destination). (David Carlier)
. Fixed bug GH-13204 (glob() fails if square bracket is in current directory).
(ndossche)
- Streams:
. Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream

View File

@@ -400,13 +400,34 @@ PHP_FUNCTION(getcwd)
/* }}} */
/* {{{ Find pathnames matching a pattern */
#if defined(ZTS) && defined(PHP_GLOB_ALTDIRFUNC)
static void *php_glob_opendir_wrapper(const char *path)
{
return VCWD_OPENDIR(path);
}
static void php_glob_closedir_wrapper(void *dir)
{
(void) closedir(dir);
}
static int php_glob_lstat_wrapper(const char *buf, zend_stat_t *sb)
{
return VCWD_LSTAT(buf, sb);
}
static int php_glob_stat_wrapper(const char *buf, zend_stat_t *sb)
{
return VCWD_STAT(buf, sb);
}
#endif
PHP_FUNCTION(glob)
{
size_t cwd_skip = 0;
#ifdef ZTS
#if defined(ZTS) && !defined(PHP_GLOB_ALTDIRFUNC)
char cwd[MAXPATHLEN];
char work_pattern[MAXPATHLEN];
char *result;
#endif
char *pattern = NULL;
size_t pattern_len;
@@ -433,28 +454,45 @@ PHP_FUNCTION(glob)
RETURN_FALSE;
}
memset(&globbuf, 0, sizeof(globbuf));
int passed_glob_flags = flags & PHP_GLOB_FLAGMASK;
#ifdef ZTS
if (!IS_ABSOLUTE_PATH(pattern, pattern_len)) {
result = VCWD_GETCWD(cwd, MAXPATHLEN);
/* System glob uses the current work directory which is not thread safe.
* The first fix is to override the functions used to open/read/... paths
* with the VCWD ones used in PHP.
* If that functionality is unavailable for whatever reason, fall back
* to prepending the current working directory to the passed path.
* However, that comes with limitations regarding meta characters
* that is not solvable in general (GH-13204). */
# ifdef PHP_GLOB_ALTDIRFUNC
globbuf.gl_opendir = php_glob_opendir_wrapper;
globbuf.gl_readdir = (struct dirent *(*)(void *)) readdir;
globbuf.gl_closedir = php_glob_closedir_wrapper;
globbuf.gl_lstat = php_glob_lstat_wrapper;
globbuf.gl_stat = php_glob_stat_wrapper;
passed_glob_flags |= PHP_GLOB_ALTDIRFUNC;
# else
char *result = VCWD_GETCWD(cwd, MAXPATHLEN);
if (!result) {
cwd[0] = '\0';
}
#ifdef PHP_WIN32
# ifdef PHP_WIN32
if (IS_SLASH(*pattern)) {
cwd[2] = '\0';
}
#endif
# endif
cwd_skip = strlen(cwd)+1;
snprintf(work_pattern, MAXPATHLEN, "%s%c%s", cwd, DEFAULT_SLASH, pattern);
pattern = work_pattern;
# endif
}
#endif
memset(&globbuf, 0, sizeof(globbuf));
globbuf.gl_offs = 0;
if (0 != (ret = php_glob(pattern, flags & PHP_GLOB_FLAGMASK, NULL, &globbuf))) {
if (0 != (ret = php_glob(pattern, passed_glob_flags, NULL, &globbuf))) {
#ifdef PHP_GLOB_NOMATCH
if (PHP_GLOB_NOMATCH == ret) {
/* Some glob implementation simply return no data if no matches

View File

@@ -0,0 +1,12 @@
--TEST--
GH-13204 (glob() fails if square bracket is in current directory)
--FILE--
<?php
chdir(__DIR__ . '/gh13204[brackets]/');
var_dump(glob('./*'));
?>
--EXPECT--
array(1) {
[0]=>
string(11) "./empty.txt"
}