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:
2
NEWS
2
NEWS
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
12
ext/standard/tests/file/gh13204.phpt
Normal file
12
ext/standard/tests/file/gh13204.phpt
Normal 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"
|
||||
}
|
||||
0
ext/standard/tests/file/gh13204[brackets]/empty.txt
Normal file
0
ext/standard/tests/file/gh13204[brackets]/empty.txt
Normal file
Reference in New Issue
Block a user