From 439f904b49d77510f0508b277d4b7d3ec0eeb8ac Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 15:18:29 +0200 Subject: [PATCH 01/12] Zend: Refactor VCWD_CHDIR_FILE() to take path length --- Zend/zend_virtual_cwd.c | 35 +++++++++++++++++------------------ Zend/zend_virtual_cwd.h | 6 +++--- main/main.c | 4 ++-- sapi/phpdbg/phpdbg_prompt.c | 2 +- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 366e13ce9b6ba..c0fd71fdd362e 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1206,39 +1206,38 @@ CWD_API zend_result virtual_chdir(const char *path) /* {{{ */ } /* }}} */ - -/* returns 0 for ok, 1 for empty string, -1 on error */ -CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path)) /* {{{ */ +CWD_API zend_result virtual_chdir_file(const char *path, size_t path_len, int (*p_chdir)(const char *path)) /* {{{ */ { - size_t length = strlen(path); char *temp; - int retval; ALLOCA_FLAG(use_heap) - if (length == 0) { - return 1; /* Can't cd to empty string */ - } - while(--length < SIZE_MAX && !IS_SLASH(path[length])) { + ZEND_ASSERT(path_len != 0 && "path must not be empty"); + while(--path_len < SIZE_MAX && !IS_SLASH(path[path_len])) { } - if (length == SIZE_MAX) { + if (path_len == SIZE_MAX) { /* No directory only file name */ errno = ENOENT; - return -1; + return FAILURE; } - if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */ - length++; + if (path_len == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, path_len+1)) { /* Also use trailing slash if this is absolute */ + path_len++; } - temp = (char *) do_alloca(length+1, use_heap); - memcpy(temp, path, length); - temp[length] = 0; + temp = (char *) do_alloca(path_len+1, use_heap); + memcpy(temp, path, path_len); + temp[path_len] = 0; #if VIRTUAL_CWD_DEBUG fprintf (stderr, "Changing directory to %s\n", temp); #endif - retval = p_chdir(temp); + int retval = p_chdir(temp); free_alloca(temp, use_heap); - return retval; + + if (retval == 0) { + return SUCCESS; + } else { + return FAILURE; + } } /* }}} */ diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 0fc2799118692..9fa5cfc2e10a5 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -173,7 +173,7 @@ CWD_API void virtual_cwd_deactivate(void); CWD_API char *virtual_getcwd_ex(size_t *length); CWD_API char *virtual_getcwd(char *buf, size_t size); CWD_API zend_result virtual_chdir(const char *path); -CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path)); +CWD_API zend_result virtual_chdir_file(const char *path, size_t path_len, int (*p_chdir)(const char *path)); CWD_API int virtual_filepath(const char *path, char **filepath); CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path); CWD_API char *virtual_realpath(const char *path, char *real_path); @@ -272,7 +272,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_OPEN_MODE(path, flags, mode) virtual_open(path, flags, mode) #define VCWD_CREAT(path, mode) virtual_creat(path, mode) #define VCWD_CHDIR(path) virtual_chdir(path) -#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, (int (*)(const char *)) virtual_chdir) +#define VCWD_CHDIR_FILE(path, path_len) virtual_chdir_file(path, path_len, (int (*)(const char *)) virtual_chdir) #define VCWD_GETWD(buf) #define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path) #define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname) @@ -326,7 +326,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_CHMOD(path, mode) chmod(path, mode) #endif -#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir) +#define VCWD_CHDIR_FILE(path, path_len) virtual_chdir_file(path, path_len, chdir) #define VCWD_GETWD(buf) getwd(buf) #define VCWD_STAT(path, buff) php_sys_stat(path, buff) #define VCWD_LSTAT(path, buff) lstat(path, buff) diff --git a/main/main.c b/main/main.c index 15a9f9a59b2be..83658f577132c 100644 --- a/main/main.c +++ b/main/main.c @@ -2536,7 +2536,7 @@ PHPAPI bool php_execute_script_ex(zend_file_handle *primary_file, zval *retval) #else php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1)); #endif - VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename)); + VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename), ZSTR_LEN(primary_file->filename)); } /* Only lookup the real file path and add it to the included_files list if already opened @@ -2639,7 +2639,7 @@ PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval *ret) if (primary_file->filename && !(SG(options) & SAPI_OPTION_NO_CHDIR)) { php_ignore_value(VCWD_GETCWD(old_cwd, OLD_CWD_SIZE-1)); - VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename)); + VCWD_CHDIR_FILE(ZSTR_VAL(primary_file->filename), ZSTR_LEN(primary_file->filename)); } zend_execute_scripts(ZEND_REQUIRE, ret, 1, primary_file); } zend_end_try(); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 2314068044fb8..a6032d3dd94be 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -427,7 +427,7 @@ PHPDBG_COMMAND(exec) /* {{{ */ PHPDBG_G(exec) = res; PHPDBG_G(exec_len) = res_len; - VCWD_CHDIR_FILE(res); + VCWD_CHDIR_FILE(res, res_len); *SG(request_info).argv = estrndup(PHPDBG_G(exec), PHPDBG_G(exec_len)); php_build_argv(NULL, &PG(http_globals)[TRACK_VARS_SERVER]); From 1c33031a48a374c17e90b2e0edab1bbbddf62935 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 16:16:37 +0200 Subject: [PATCH 02/12] Remove duplicate test conditions --- .../file/readlink_realpath_variation3.phpt | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/ext/standard/tests/file/readlink_realpath_variation3.phpt b/ext/standard/tests/file/readlink_realpath_variation3.phpt index 44a53f0dfb353..3c287ec35d0e2 100644 --- a/ext/standard/tests/file/readlink_realpath_variation3.phpt +++ b/ext/standard/tests/file/readlink_realpath_variation3.phpt @@ -4,49 +4,34 @@ Test readlink() and realpath() functions: usage variation - invalid args --EXPECTF-- *** Testing readlink() and realpath() : usage variations *** -*** Testing readlink() and realpath() with linkname as empty string, NULL and single space *** --- Iteration1 -- +*** Testing readlink() and realpath() with link name as empty string, NULL and single space *** +readlink with link as spaces Warning: readlink(): %s in %s on line %d bool(false) -%s --- Iteration2 -- - -Warning: readlink(): %s in %s on line %d -bool(false) -%s --- Iteration3 -- - -Warning: readlink(): %s in %s on line %d +realpath with link as spaces bool(false) -string(%d) "%s" --- Iteration4 -- +readlink with link as empty string Warning: readlink(): %s in %s on line %d bool(false) +realpath with link as empty string string(%d) "%s" Done From 84e39bb62b64a7ff746568a52f277b3242168457 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 16:17:00 +0200 Subject: [PATCH 03/12] Zend: Refactor virtual_file_ex() to take path length --- Zend/zend_virtual_cwd.c | 70 ++++++++++++++++++++++------------ Zend/zend_virtual_cwd.h | 2 +- ext/phar/phar_object.c | 2 +- ext/zip/php_zip.c | 2 +- main/fopen_wrappers.c | 2 +- main/php_open_temporary_file.c | 3 +- 6 files changed, 51 insertions(+), 30 deletions(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index c0fd71fdd362e..5c46f04404af9 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1004,9 +1004,8 @@ static size_t tsrm_realpath_r(char *path, size_t start, size_t len, int *ll, tim /* Resolve path relatively to state and put the real path into state */ /* returns 0 for ok, 1 for error, -1 if (path_length >= MAXPATHLEN-1) */ -CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath) /* {{{ */ +CWD_API int virtual_file_ex(cwd_state *state, const char *path, size_t path_length, verify_path_func verify_path, int use_realpath) /* {{{ */ { - size_t path_length = strlen(path); char resolved_path[MAXPATHLEN]; size_t start = 1; int ll = 0; @@ -1202,7 +1201,8 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func CWD_API zend_result virtual_chdir(const char *path) /* {{{ */ { - return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, CWD_REALPATH) ? FAILURE : SUCCESS; + size_t path_length = strlen(path); + return virtual_file_ex(&CWDG(cwd), path, path_length, php_is_dir_ok, CWD_REALPATH) ? FAILURE : SUCCESS; } /* }}} */ @@ -1246,16 +1246,18 @@ CWD_API char *virtual_realpath(const char *path, char *real_path) /* {{{ */ cwd_state new_state; char *retval; char cwd[MAXPATHLEN]; + size_t path_length = strlen(path); /* realpath("") returns CWD */ - if (!*path) { + if (path_length == 0) { new_state.cwd = (char*)emalloc(1); new_state.cwd[0] = '\0'; new_state.cwd_length = 0; if (VCWD_GETCWD(cwd, MAXPATHLEN)) { path = cwd; + path_length = strlen(cwd); } - } else if (!IS_ABSOLUTE_PATH(path, strlen(path))) { + } else if (!IS_ABSOLUTE_PATH(path, path_length)) { CWD_STATE_COPY(&new_state, &CWDG(cwd)); } else { new_state.cwd = (char*)emalloc(1); @@ -1263,7 +1265,7 @@ CWD_API char *virtual_realpath(const char *path, char *real_path) /* {{{ */ new_state.cwd_length = 0; } - if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)==0) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)==0) { size_t len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length; memcpy(real_path, new_state.cwd, len); @@ -1282,10 +1284,11 @@ CWD_API char *virtual_realpath(const char *path, char *real_path) /* {{{ */ CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path) /* {{{ */ { cwd_state new_state; + size_t path_length = strlen(path); int retval; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - retval = virtual_file_ex(&new_state, path, verify_path, CWD_FILEPATH); + retval = virtual_file_ex(&new_state, path, path_length, verify_path, CWD_FILEPATH); *filepath = new_state.cwd; @@ -1304,6 +1307,7 @@ CWD_API int virtual_filepath(const char *path, char **filepath) /* {{{ */ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */ { cwd_state new_state; + size_t path_length = strlen(path); FILE *f; if (path[0] == '\0') { /* Fail to open empty path */ @@ -1311,7 +1315,7 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */ } CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); return NULL; } @@ -1331,10 +1335,11 @@ CWD_API FILE *virtual_fopen(const char *path, const char *mode) /* {{{ */ CWD_API int virtual_access(const char *pathname, int mode) /* {{{ */ { cwd_state new_state; + size_t path_length = strlen(pathname); int ret; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1355,10 +1360,11 @@ CWD_API int virtual_access(const char *pathname, int mode) /* {{{ */ CWD_API int virtual_utime(const char *filename, struct utimbuf *buf) /* {{{ */ { cwd_state new_state; + size_t filename_length = strlen(filename); int ret; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1378,10 +1384,11 @@ CWD_API int virtual_utime(const char *filename, struct utimbuf *buf) /* {{{ */ CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */ { cwd_state new_state; + size_t filename_length = strlen(filename); int ret; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1413,10 +1420,11 @@ CWD_API int virtual_chmod(const char *filename, mode_t mode) /* {{{ */ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int link) /* {{{ */ { cwd_state new_state; + size_t filename_length = strlen(filename); int ret; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, filename, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, filename, filename_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1440,10 +1448,11 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */ { cwd_state new_state; + size_t path_length = strlen(path); int f; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_FILEPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1476,10 +1485,11 @@ CWD_API int virtual_open(const char *path, int flags, ...) /* {{{ */ CWD_API int virtual_creat(const char *path, mode_t mode) /* {{{ */ { cwd_state new_state; + size_t path_length = strlen(path); int f; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_FILEPATH)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_FILEPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1495,17 +1505,19 @@ CWD_API int virtual_rename(const char *oldname, const char *newname) /* {{{ */ { cwd_state old_state; cwd_state new_state; + size_t old_name_length = strlen(oldname); + size_t new_name_length = strlen(newname); int retval; CWD_STATE_COPY(&old_state, &CWDG(cwd)); - if (virtual_file_ex(&old_state, oldname, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&old_state, oldname, old_name_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&old_state); return -1; } oldname = old_state.cwd; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, newname, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, newname, new_name_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&old_state); CWD_STATE_FREE_ERR(&new_state); return -1; @@ -1532,9 +1544,10 @@ CWD_API int virtual_stat(const char *path, zend_stat_t *buf) /* {{{ */ { cwd_state new_state; int retval; + size_t path_length = strlen(path); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1550,9 +1563,10 @@ CWD_API int virtual_lstat(const char *path, zend_stat_t *buf) /* {{{ */ { cwd_state new_state; int retval; + size_t path_length = strlen(path); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1568,9 +1582,10 @@ CWD_API int virtual_unlink(const char *path) /* {{{ */ { cwd_state new_state; int retval; + size_t path_length = strlen(path); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, path, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1590,9 +1605,10 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode) /* {{{ */ { cwd_state new_state; int retval; + size_t path_length = strlen(pathname); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, pathname, NULL, CWD_FILEPATH)) { + if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_FILEPATH)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1611,9 +1627,10 @@ CWD_API int virtual_rmdir(const char *pathname) /* {{{ */ { cwd_state new_state; int retval; + size_t path_length = strlen(pathname); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, pathname, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); return -1; } @@ -1636,9 +1653,10 @@ CWD_API DIR *virtual_opendir(const char *pathname) /* {{{ */ { cwd_state new_state; DIR *retval; + size_t path_length = strlen(pathname); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, pathname, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_REALPATH)) { CWD_STATE_FREE_ERR(&new_state); return NULL; } @@ -1717,16 +1735,18 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path) /* {{{ */ { cwd_state new_state; char cwd[MAXPATHLEN]; + size_t path_length = strlen(path); /* realpath("") returns CWD */ - if (!*path) { + if (path_length == 0) { new_state.cwd = (char*)emalloc(1); new_state.cwd[0] = '\0'; new_state.cwd_length = 0; if (VCWD_GETCWD(cwd, MAXPATHLEN)) { path = cwd; + path_length = strlen(cwd); } - } else if (!IS_ABSOLUTE_PATH(path, strlen(path)) && + } else if (!IS_ABSOLUTE_PATH(path, path_length) && VCWD_GETCWD(cwd, MAXPATHLEN)) { new_state.cwd = estrdup(cwd); new_state.cwd_length = strlen(cwd); @@ -1736,7 +1756,7 @@ CWD_API char *tsrm_realpath(const char *path, char *real_path) /* {{{ */ new_state.cwd_length = 0; } - if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)) { efree(new_state.cwd); return NULL; } diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 9fa5cfc2e10a5..95344c00aa07a 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -206,7 +206,7 @@ CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group, int li #define CWD_FILEPATH 1 /* resolve symlinks if file is exist otherwise expand */ #define CWD_REALPATH 2 /* call realpath(), resolve symlinks. File must exist */ -CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath); +CWD_API int virtual_file_ex(cwd_state *state, const char *path, size_t path_length, verify_path_func verify_path, int use_realpath); CWD_API char *tsrm_realpath(const char *path, char *real_path); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 688e3981e67d9..dd1a57ffd1ec8 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -4130,7 +4130,7 @@ static int phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, new_state.cwd[0] = DEFAULT_SLASH; new_state.cwd[1] = '\0'; new_state.cwd_length = 1; - if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 || + if (virtual_file_ex(&new_state, entry->filename, entry->filename_len, NULL, CWD_EXPAND) != 0 || new_state.cwd_length <= 1) { if (EINVAL == errno && entry->filename_len > 50) { char *tmp = estrndup(entry->filename, 50); diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 9fc0af4fcaca4..8054cd4177199 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -152,7 +152,7 @@ static int php_zip_extract_file(struct zip * za, char *dest, const char *file, s /* Clean/normlize the path and then transform any path (absolute or relative) to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt) */ - virtual_file_ex(&new_state, file, NULL, CWD_EXPAND); + virtual_file_ex(&new_state, file, file_len, NULL, CWD_EXPAND); path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length); if(!path_cleaned) { CWD_STATE_FREE(new_state.cwd); diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index 99a082846b481..952bb48924ddd 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -834,7 +834,7 @@ PHPAPI char *expand_filepath_with_mode(const char *filepath, char *real_path, co new_state.cwd = estrdup(cwd); new_state.cwd_length = strlen(cwd); - if (virtual_file_ex(&new_state, filepath, NULL, realpath_mode)) { + if (virtual_file_ex(&new_state, filepath, path_len, NULL, realpath_mode)) { efree(new_state.cwd); return NULL; } diff --git a/main/php_open_temporary_file.c b/main/php_open_temporary_file.c index b45537935a570..31e9af5d136af 100644 --- a/main/php_open_temporary_file.c +++ b/main/php_open_temporary_file.c @@ -131,8 +131,9 @@ static int php_do_open_temporary_file(const char *path, const char *pfx, zend_st new_state.cwd = estrdup(cwd); new_state.cwd_length = strlen(cwd); + size_t path_length = strlen(path); - if (virtual_file_ex(&new_state, path, NULL, CWD_REALPATH)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_REALPATH)) { efree(new_state.cwd); return -1; } From 64a2693c74df87a8cc74b46c45f6919705fcf996 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 16:53:50 +0200 Subject: [PATCH 04/12] Zend: Refactor virtual_rename() to take path lengths --- Zend/zend_virtual_cwd.c | 25 ++++++++++--------------- Zend/zend_virtual_cwd.h | 16 +++++++++++----- ext/soap/php_sdl.c | 7 ++++--- ext/standard/basic_functions.c | 2 +- main/streams/plain_wrapper.c | 10 +++++++--- win32/ioutil.c | 13 +++++-------- win32/ioutil.h | 29 ++++++++++++----------------- 7 files changed, 50 insertions(+), 52 deletions(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 5c46f04404af9..4e2b98365275d 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1501,36 +1501,31 @@ CWD_API int virtual_creat(const char *path, mode_t mode) /* {{{ */ } /* }}} */ -CWD_API int virtual_rename(const char *oldname, const char *newname) /* {{{ */ +CWD_API zend_result virtual_rename(const char *old_name, size_t old_name_len, const char *new_name, size_t new_name_len) /* {{{ */ { cwd_state old_state; cwd_state new_state; - size_t old_name_length = strlen(oldname); - size_t new_name_length = strlen(newname); - int retval; CWD_STATE_COPY(&old_state, &CWDG(cwd)); - if (virtual_file_ex(&old_state, oldname, old_name_length, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&old_state, old_name, old_name_len, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&old_state); - return -1; + return FAILURE; } - oldname = old_state.cwd; CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, newname, new_name_length, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, new_name, new_name_len, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&old_state); CWD_STATE_FREE_ERR(&new_state); - return -1; + return FAILURE; } - newname = new_state.cwd; - /* rename on windows will fail if newname already exists. - MoveFileEx has to be used */ + zend_result retval; #ifdef ZEND_WIN32 - /* MoveFileEx returns 0 on failure, other way 'round for this function */ - retval = php_win32_ioutil_rename(oldname, newname); + /* rename on windows will fail if new_name already exists. MoveFileEx has to be used */ + /* MoveFileEx returns 0 on failure, other way round for this function */ + retval = php_win32_ioutil_rename(old_state.cwd, old_state.cwd_length, new_name, new_name_len); #else - retval = rename(oldname, newname); + retval = virtual_rename_native(old_state.cwd, old_state.cwd_length, new_state.cwd, new_state.cwd_length); #endif CWD_STATE_FREE_ERR(&old_state); diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 95344c00aa07a..f0d195254ee4c 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -180,7 +180,7 @@ CWD_API char *virtual_realpath(const char *path, char *real_path); CWD_API FILE *virtual_fopen(const char *path, const char *mode); CWD_API int virtual_open(const char *path, int flags, ...); CWD_API int virtual_creat(const char *path, mode_t mode); -CWD_API int virtual_rename(const char *oldname, const char *newname); +CWD_API zend_result virtual_rename(const char *old_name, size_t old_name_len, const char *new_name, size_t new_name_len); CWD_API int virtual_stat(const char *path, zend_stat_t *buf); CWD_API int virtual_lstat(const char *path, zend_stat_t *buf); CWD_API int virtual_unlink(const char *path); @@ -254,6 +254,12 @@ CWD_API zend_long realpath_cache_size(void); CWD_API zend_long realpath_cache_max_buckets(void); CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void); + +static zend_always_inline zend_result virtual_rename_native(const char *old_name, + ZEND_ATTRIBUTE_UNUSED size_t old_name_len, const char *new_name, ZEND_ATTRIBUTE_UNUSED size_t new_name_len) { + return (rename(old_name, new_name) == 0) ? SUCCESS : FAILURE; +} + #ifdef CWD_EXPORTS extern void virtual_cwd_main_cwd_init(uint8_t); #endif @@ -275,7 +281,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_CHDIR_FILE(path, path_len) virtual_chdir_file(path, path_len, (int (*)(const char *)) virtual_chdir) #define VCWD_GETWD(buf) #define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path) -#define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname) +#define VCWD_RENAME(old_name, old_name_length, new_name, new_name_length) virtual_rename(old_name, old_name_length, new_name, new_name_length) #define VCWD_STAT(path, buff) virtual_stat(path, buff) # define VCWD_LSTAT(path, buff) virtual_lstat(path, buff) #define VCWD_UNLINK(path) virtual_unlink(path) @@ -304,7 +310,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_FOPEN(path, mode) php_win32_ioutil_fopen(path, mode) #define VCWD_OPEN(path, flags) php_win32_ioutil_open(path, flags) #define VCWD_OPEN_MODE(path, flags, mode) php_win32_ioutil_open(path, flags, mode) -# define VCWD_RENAME(oldname, newname) php_win32_ioutil_rename(oldname, newname) +#define VCWD_RENAME(old_name, old_name_length, new_name, new_name_length) php_win32_ioutil_rename(old_name, old_name_length, new_name, new_name_length) #define VCWD_MKDIR(pathname, mode) php_win32_ioutil_mkdir(pathname, mode) #define VCWD_RMDIR(pathname) php_win32_ioutil_rmdir(pathname) #define VCWD_UNLINK(path) php_win32_ioutil_unlink(path) @@ -316,8 +322,8 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_FOPEN(path, mode) fopen(path, mode) #define VCWD_OPEN(path, flags) open(path, flags) #define VCWD_OPEN_MODE(path, flags, mode) open(path, flags, mode) -# define VCWD_RENAME(oldname, newname) rename(oldname, newname) -#define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode) +#define VCWD_RENAME(old_name, old_name_len, new_name, new_name_len) virtual_rename_native(old_name, old_name_len, new_name, new_name_len) +#define VCWD_MKDIR(path, mode) mkdir(path, mode) #define VCWD_RMDIR(pathname) rmdir(pathname) #define VCWD_UNLINK(path) unlink(path) #define VCWD_CHDIR(path) chdir(path) diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index 68565e72dfa2e..c78ca3214fea5 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -2088,7 +2088,7 @@ static void sdl_serialize_soap_body(const sdlSoapBindingFunctionBodyPtr body, co } } -static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl) +static void add_sdl_to_cache(const char *fn, size_t fn_len, const char *uri, time_t t, sdlPtr sdl) { smart_str buf = {0}; smart_str *out = &buf; @@ -2363,7 +2363,7 @@ static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr s /* Make sure that incomplete files (e.g. due to disk space issues, see bug #66150) are not utilised. */ if (valid_file) { /* This is allowed to fail, this means that another process was raced to create the file. */ - if (VCWD_RENAME(ZSTR_VAL(temp_file_path), fn) < 0) { + if (VCWD_RENAME(ZSTR_VAL(temp_file_path), ZSTR_LEN(temp_file_path), fn, fn_len) < 0) { VCWD_UNLINK(ZSTR_VAL(temp_file_path)); } } @@ -3329,7 +3329,8 @@ sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl) if ((cache_wsdl & WSDL_CACHE_DISK) && key) { if (sdl) { - add_sdl_to_cache(key, uri, t, sdl); + // TODO Is it possible to know key_len before? + add_sdl_to_cache(key, strlen(key), uri, t, sdl); } efree(key); } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 67276adb1627e..13f55cdaa9b1c 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2379,7 +2379,7 @@ PHP_FUNCTION(move_uploaded_file) RETURN_FALSE; } - if (VCWD_RENAME(path, new_path) == 0) { + if (VCWD_RENAME(path, path_len, new_path, new_path_len) == 0) { successful = 1; #ifndef PHP_WIN32 oldmask = umask(077); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index fb2addb9e6de2..ee0daa314f21c 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1274,12 +1274,14 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f return 0; } + size_t url_from_len = strlen(url_from); + size_t url_to_len = strlen(url_to); #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url_from, strlen(url_from))) { + if (!php_win32_check_trailing_space(url_from, url_from_len)) { php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); return 0; } - if (!php_win32_check_trailing_space(url_to, strlen(url_to))) { + if (!php_win32_check_trailing_space(url_to, url_to_len)) { php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); return 0; } @@ -1287,17 +1289,19 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f if (strncasecmp(url_from, "file://", sizeof("file://") - 1) == 0) { url_from += sizeof("file://") - 1; + url_from_len -= sizeof("file://"); } if (strncasecmp(url_to, "file://", sizeof("file://") - 1) == 0) { url_to += sizeof("file://") - 1; + url_to_len -= sizeof("file://"); } if (php_check_open_basedir(url_from) || php_check_open_basedir(url_to)) { return 0; } - ret = VCWD_RENAME(url_from, url_to); + ret = VCWD_RENAME(url_from, url_from_len, url_to, url_to_len); if (ret == -1) { #ifndef PHP_WIN32 diff --git a/win32/ioutil.c b/win32/ioutil.c index a6f2fe2ae2fc1..8ba8cd1dc900b 100644 --- a/win32/ioutil.c +++ b/win32/ioutil.c @@ -464,21 +464,18 @@ PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path) return ret; }/*}}}*/ -PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname) +PW32IO zend_result php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname) {/*{{{*/ - int ret = 0; - - PHP_WIN32_IOUTIL_CHECK_PATH_W(oldname, -1, 0) - PHP_WIN32_IOUTIL_CHECK_PATH_W(newname, -1, 0) - + PHP_WIN32_IOUTIL_CHECK_PATH_W(oldname, FAILURE, 0) + PHP_WIN32_IOUTIL_CHECK_PATH_W(newname, FAILURE, 0) if (!MoveFileExW(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED)) { DWORD err = GetLastError(); - ret = -1; SET_ERRNO_FROM_WIN32_CODE(err); + return FAILURE; } - return ret; + return SUCCESS; }/*}}}*/ PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len) diff --git a/win32/ioutil.h b/win32/ioutil.h index f6105a87f2468..90f17d3ff5b98 100644 --- a/win32/ioutil.h +++ b/win32/ioutil.h @@ -264,7 +264,7 @@ PW32IO size_t php_win32_ioutil_dirname(char *buf, size_t len); PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...); PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path); -PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname); +PW32IO zend_result php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname); PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len); PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path); PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode); @@ -418,47 +418,42 @@ __forceinline static FILE *php_win32_ioutil_fopen(const char *patha, const char return ret; }/*}}}*/ -__forceinline static int php_win32_ioutil_rename(const char *oldnamea, const char *newnamea) +__forceinline static zend_result php_win32_ioutil_rename(const char *old_name_a, size_t old_name_a_len, const char *new_name_a, size_t new_name_a_len) {/*{{{*/ wchar_t *oldnamew; wchar_t *newnamew; - int ret; - DWORD err = 0; - oldnamew = php_win32_ioutil_any_to_w(oldnamea); + oldnamew = php_win32_ioutil_conv_any_to_w(old_name_a, old_name_a_len, PHP_WIN32_CP_IGNORE_LEN_P); if (!oldnamew) { SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); - return -1; + return FAILURE; } - PHP_WIN32_IOUTIL_CHECK_PATH_W(oldnamew, -1, 1) + PHP_WIN32_IOUTIL_CHECK_PATH_W(oldnamew, FAILURE, 1) - newnamew = php_win32_ioutil_any_to_w(newnamea); + newnamew = php_win32_ioutil_conv_any_to_w(new_name_a, new_name_a_len, PHP_WIN32_CP_IGNORE_LEN_P); if (!newnamew) { free(oldnamew); SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); - return -1; + return FAILURE; } else { size_t newnamew_len = wcslen(newnamew); if (!PHP_WIN32_IOUTIL_PATH_IS_OK_W(newnamew, newnamew_len)) { free(oldnamew); free(newnamew); SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED); - return -1; + return FAILURE; } } - ret = php_win32_ioutil_rename_w(oldnamew, newnamew); - if (0 > ret) { - err = GetLastError(); + zend_result ret = php_win32_ioutil_rename_w(oldnamew, newnamew); + if (ret == FAILURE) { + DWORD err = GetLastError(); + SET_ERRNO_FROM_WIN32_CODE(err); } free(oldnamew); free(newnamew); - if (0 > ret) { - SET_ERRNO_FROM_WIN32_CODE(err); - } - return ret; }/*}}}*/ From 60782d28fa85ac79fb6f4c8c3c221749a4c1bd1e Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 17:02:13 +0200 Subject: [PATCH 05/12] ext/standard: Use zend_string for path of move_uploaded_file() --- ext/standard/basic_functions.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 13f55cdaa9b1c..752fa9ab46232 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2354,8 +2354,9 @@ PHP_FUNCTION(is_uploaded_file) /* {{{ Move a file if and only if it was created by an upload */ PHP_FUNCTION(move_uploaded_file) { - char *path, *new_path; - size_t path_len, new_path_len; + zend_string *path; + char *new_path; + size_t new_path_len; bool successful = 0; #ifndef PHP_WIN32 @@ -2363,7 +2364,7 @@ PHP_FUNCTION(move_uploaded_file) #endif ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STRING(path, path_len) + Z_PARAM_STR(path) // TODO Should this use Z_PARAM_PATH_STR() ? Z_PARAM_PATH(new_path, new_path_len) ZEND_PARSE_PARAMETERS_END(); @@ -2371,7 +2372,7 @@ PHP_FUNCTION(move_uploaded_file) RETURN_FALSE; } - if (!zend_hash_str_exists(SG(rfc1867_uploaded_files), path, path_len)) { + if (!zend_hash_exists(SG(rfc1867_uploaded_files), path)) { RETURN_FALSE; } @@ -2379,7 +2380,7 @@ PHP_FUNCTION(move_uploaded_file) RETURN_FALSE; } - if (VCWD_RENAME(path, path_len, new_path, new_path_len) == 0) { + if (VCWD_RENAME(ZSTR_VAL(path), ZSTR_LEN(path), new_path, new_path_len) == 0) { successful = 1; #ifndef PHP_WIN32 oldmask = umask(077); @@ -2391,15 +2392,15 @@ PHP_FUNCTION(move_uploaded_file) php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); } #endif - } else if (php_copy_file_ex(path, new_path, STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) { - VCWD_UNLINK(path); + } else if (php_copy_file_ex(ZSTR_VAL(path), new_path, STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) { + VCWD_UNLINK(ZSTR_VAL(path)); successful = 1; } if (successful) { - zend_hash_str_del(SG(rfc1867_uploaded_files), path, path_len); + zend_hash_del(SG(rfc1867_uploaded_files), path); } else { - php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", path, new_path); + php_error_docref(NULL, E_WARNING, "Unable to move \"%s\" to \"%s\"", ZSTR_VAL(path), new_path); } RETURN_BOOL(successful); From 2eb31b59eef27c232b1ec29ccc4c98f5b554a413 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 17:25:24 +0200 Subject: [PATCH 06/12] Use CLEAN section in some tests --- ext/standard/tests/file/lstat_stat_variation2.phpt | 9 +++++---- ext/standard/tests/file/rename_variation.phpt | 8 +++++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ext/standard/tests/file/lstat_stat_variation2.phpt b/ext/standard/tests/file/lstat_stat_variation2.phpt index efc03096a7bd6..c3220d8c8b7ea 100644 --- a/ext/standard/tests/file/lstat_stat_variation2.phpt +++ b/ext/standard/tests/file/lstat_stat_variation2.phpt @@ -8,12 +8,12 @@ $file_path = __DIR__; require("file.inc"); /* create temp directory */ -mkdir("$file_path/lstat_stat_variation1/"); // temp dir +mkdir("$file_path/lstat_stat_variation2/"); // temp dir // renaming a directory and check stat echo "*** Testing stat() for directory after being renamed ***\n"; -$old_dirname = "$file_path/lstat_stat_variation1"; -$new_dirname = "$file_path/lstat_stat_variation1a"; +$old_dirname = "$file_path/lstat_stat_variation2"; +$new_dirname = "$file_path/lstat_stat_variation2a"; $old_stat = stat($old_dirname); clearstatcache(); var_dump( rename($old_dirname, $new_dirname) ); @@ -36,7 +36,8 @@ echo "\n--- Done ---"; --CLEAN-- --EXPECT-- *** Testing stat() for directory after being renamed *** diff --git a/ext/standard/tests/file/rename_variation.phpt b/ext/standard/tests/file/rename_variation.phpt index b86c5c80973d5..5939db5abe769 100644 --- a/ext/standard/tests/file/rename_variation.phpt +++ b/ext/standard/tests/file/rename_variation.phpt @@ -42,11 +42,13 @@ foreach($src_filenames as $src_filename) { unlink($dest_filename); } -// clean the temp dir and file -rmdir("$file_path/rename_variation"); - echo "Done\n"; ?> +--CLEAN-- + --EXPECTF-- *** Testing rename() : rename files across directories *** -- Iteration 1 -- From 8d5e3a9be265c0e7fa980ed8cfc61caedd0035eb Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 19:58:41 +0200 Subject: [PATCH 07/12] streams: Refactor rename stream op to use zend_string --- ext/phar/stream.c | 32 ++++++------- ext/phar/stream.h | 2 +- ext/standard/file.c | 11 ++--- ext/standard/ftp_fopen_wrapper.c | 8 ++-- main/php_streams.h | 2 +- main/streams/plain_wrapper.c | 78 ++++++++++++++++---------------- main/streams/userspace.c | 8 ++-- 7 files changed, 69 insertions(+), 72 deletions(-) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 79f02ff70db5e..9da615e752088 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -741,7 +741,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int } /* }}} */ -static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) /* {{{ */ +static bool phar_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context) /* {{{ */ { php_url *resource_from, *resource_to; char *error; @@ -753,8 +753,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from error = NULL; - if ((resource_from = phar_parse_url(wrapper, url_from, "wb", options|PHP_STREAM_URL_STAT_QUIET)) == NULL) { - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_from); + if ((resource_from = phar_parse_url(wrapper, ZSTR_VAL(url_from), "wb", options|PHP_STREAM_URL_STAT_QUIET)) == NULL) { + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_from)); return 0; } if (SUCCESS != phar_get_archive(&pfrom, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, &error)) { @@ -769,9 +769,9 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from return 0; } - if ((resource_to = phar_parse_url(wrapper, url_to, "wb", options|PHP_STREAM_URL_STAT_QUIET)) == NULL) { + if ((resource_to = phar_parse_url(wrapper, ZSTR_VAL(url_to), "wb", options|PHP_STREAM_URL_STAT_QUIET)) == NULL) { php_url_free(resource_from); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_to)); return 0; } if (SUCCESS != phar_get_archive(&pto, ZSTR_VAL(resource_to->host), ZSTR_LEN(resource_to->host), NULL, 0, &error)) { @@ -790,7 +790,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (!zend_string_equals(resource_from->host, resource_to->host)) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\", not within the same phar archive", url_from, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\", not within the same phar archive", ZSTR_VAL(url_from), ZSTR_VAL(url_to)); return 0; } @@ -798,28 +798,28 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (!resource_from->scheme || !resource_from->host || !resource_from->path) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", url_from, url_to, url_from); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_from)); return 0; } if (!resource_to->scheme || !resource_to->host || !resource_to->path) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", url_from, url_to, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_to)); return 0; } if (!zend_string_equals_literal_ci(resource_from->scheme, "phar")) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": not a phar stream url \"%s\"", url_from, url_to, url_from); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": not a phar stream url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_from)); return 0; } if (!zend_string_equals_literal_ci(resource_to->scheme, "phar")) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": not a phar stream url \"%s\"", url_from, url_to, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": not a phar stream url \"%s\"", ZSTR_VAL(url_from), ZSTR_VAL(url_to), ZSTR_VAL(url_to)); return 0; } @@ -828,7 +828,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (SUCCESS != phar_get_archive(&phar, ZSTR_VAL(resource_from->host), host_len, NULL, 0, &error)) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", ZSTR_VAL(url_from), ZSTR_VAL(url_to), error); efree(error); return 0; } @@ -836,7 +836,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (phar->is_persistent && FAILURE == phar_copy_on_write(&phar)) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": could not make cached phar writeable", url_from, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": could not make cached phar writeable", ZSTR_VAL(url_from), ZSTR_VAL(url_to)); return 0; } @@ -847,7 +847,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (entry->is_deleted) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\" from extracted phar archive, source has been deleted", url_from, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\" from extracted phar archive, source has been deleted", ZSTR_VAL(url_from), ZSTR_VAL(url_to)); return 0; } /* transfer all data over to the new entry */ @@ -867,7 +867,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (FAILURE == phar_copy_entry_fp(source, entry, &error)) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", ZSTR_VAL(url_from), ZSTR_VAL(url_to), error); efree(error); zend_hash_str_del(&(phar->manifest), entry->filename, strlen(entry->filename)); return 0; @@ -882,7 +882,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from /* file does not exist */ php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\" from extracted phar archive, source does not exist", url_from, url_to); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\" from extracted phar archive, source does not exist", ZSTR_VAL(url_from), ZSTR_VAL(url_to)); return 0; } @@ -963,7 +963,7 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from if (error) { php_url_free(resource_from); php_url_free(resource_to); - php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); + php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", ZSTR_VAL(url_from), ZSTR_VAL(url_to), error); efree(error); return 0; } diff --git a/ext/phar/stream.h b/ext/phar/stream.h index 732da3a0b3f2c..ae76eb9b57093 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -23,7 +23,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const void phar_entry_remove(phar_entry_data *idata, char **error); static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC); -static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context); +static bool phar_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context); diff --git a/ext/standard/file.c b/ext/standard/file.c index 6b6b43b1fb672..e647176832096 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1257,20 +1257,19 @@ PHPAPI PHP_FUNCTION(fpassthru) /* {{{ Rename a file */ PHP_FUNCTION(rename) { - char *old_name, *new_name; - size_t old_name_len, new_name_len; + zend_string *old_name, *new_name; zval *zcontext = NULL; php_stream_wrapper *wrapper; php_stream_context *context; ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_PATH(old_name, old_name_len) - Z_PARAM_PATH(new_name, new_name_len) + Z_PARAM_PATH_STR(old_name) + Z_PARAM_PATH_STR(new_name) Z_PARAM_OPTIONAL Z_PARAM_RESOURCE_OR_NULL(zcontext) ZEND_PARSE_PARAMETERS_END(); - wrapper = php_stream_locate_url_wrapper(old_name, NULL, 0); + wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(old_name), NULL, 0); if (!wrapper || !wrapper->wops) { php_error_docref(NULL, E_WARNING, "Unable to locate stream wrapper"); @@ -1282,7 +1281,7 @@ PHP_FUNCTION(rename) RETURN_FALSE; } - if (wrapper != php_stream_locate_url_wrapper(new_name, NULL, 0)) { + if (wrapper != php_stream_locate_url_wrapper(ZSTR_VAL(new_name), NULL, 0)) { php_error_docref(NULL, E_WARNING, "Cannot rename a file across wrapper types"); RETURN_FALSE; } diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 51b7b311a9540..44fb4395409f3 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -941,15 +941,15 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i /* }}} */ /* {{{ php_stream_ftp_rename */ -static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) +static bool php_stream_ftp_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context) { php_stream *stream = NULL; php_url *resource_from = NULL, *resource_to = NULL; int result; char tmp_line[512]; - resource_from = php_url_parse(url_from); - resource_to = php_url_parse(url_to); + resource_from = php_url_parse(ZSTR_VAL(url_from)); + resource_to = php_url_parse(ZSTR_VAL(url_to)); /* Must be same scheme (ftp/ftp or ftps/ftps), same host, and same port (or a 21/0 0/21 combination which is also "same") Also require paths to/from */ @@ -969,7 +969,7 @@ static int php_stream_ftp_rename(php_stream_wrapper *wrapper, const char *url_fr goto rename_errexit; } - stream = php_ftp_fopen_connect(wrapper, url_from, "r", 0, NULL, context, NULL, NULL, NULL, NULL); + stream = php_ftp_fopen_connect(wrapper, ZSTR_VAL(url_from), "r", 0, NULL, context, NULL, NULL, NULL, NULL); if (!stream) { if (options & REPORT_ERRORS) { php_error_docref(NULL, E_WARNING, "Unable to connect to %s", ZSTR_VAL(resource_from->host)); diff --git a/main/php_streams.h b/main/php_streams.h index 33b14ff4eb3df..f14a6cb1834b0 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -148,7 +148,7 @@ typedef struct _php_stream_wrapper_ops { int (*unlink)(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); /* rename a file */ - int (*rename)(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context); + bool (*rename)(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); /* Create/Remove directory */ int (*stream_mkdir)(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index ee0daa314f21c..4fb905b9de427 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1266,44 +1266,42 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, return 1; } -static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) +static bool php_plain_files_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context) { - int ret; - if (!url_from || !url_to) { - return 0; + return false; } - size_t url_from_len = strlen(url_from); - size_t url_to_len = strlen(url_to); #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url_from, url_from_len)) { - php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); - return 0; + if (!php_win32_check_trailing_space(ZSTR_VAL(url_from), ZSTR_LEN(url_from))) { + php_win32_docref2_from_error(ERROR_INVALID_NAME, ZSTR_VAL(url_from), ZSTR_VAL(url_to)); + return false; } - if (!php_win32_check_trailing_space(url_to, url_to_len)) { - php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); - return 0; + if (!php_win32_check_trailing_space(ZSTR_VAL(url_to), ZSTR_LEN(url_to))) { + php_win32_docref2_from_error(ERROR_INVALID_NAME, ZSTR_VAL(url_from), ZSTR_VAL(url_to)); + return false; } #endif - if (strncasecmp(url_from, "file://", sizeof("file://") - 1) == 0) { - url_from += sizeof("file://") - 1; - url_from_len -= sizeof("file://"); + const char *url_from_ptr = ZSTR_VAL(url_from); + size_t url_from_len = ZSTR_LEN(url_from); + if (zend_string_starts_with_literal_ci(url_from, "file://")) { + url_from_ptr += strlen("file://"); + url_from_len -= strlen("file://"); } - if (strncasecmp(url_to, "file://", sizeof("file://") - 1) == 0) { - url_to += sizeof("file://") - 1; - url_to_len -= sizeof("file://"); + const char *url_to_ptr = ZSTR_VAL(url_to); + size_t url_to_len = ZSTR_LEN(url_to); + if (zend_string_starts_with_literal_ci(url_to, "file://")) { + url_to_ptr += strlen("file://"); + url_to_len -= strlen("file://"); } - if (php_check_open_basedir(url_from) || php_check_open_basedir(url_to)) { - return 0; + if (php_check_open_basedir(url_from_ptr) || php_check_open_basedir(url_to_ptr)) { + return false; } - ret = VCWD_RENAME(url_from, url_from_len, url_to, url_to_len); - - if (ret == -1) { + if (VCWD_RENAME(url_from_ptr, url_from_len, url_to_ptr, url_to_len) == FAILURE) { #ifndef PHP_WIN32 # ifdef EXDEV if (errno == EXDEV) { @@ -1312,10 +1310,10 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f /* not sure what to do in ZTS case, umask is not thread-safe */ int oldmask = umask(077); # endif - int success = 0; - if (php_copy_file(url_from, url_to) == SUCCESS) { - if (VCWD_STAT(url_from, &sb) == 0) { - success = 1; + bool success = false; + if (php_copy_file(url_from_ptr, url_to_ptr) == SUCCESS) { + if (VCWD_STAT(url_from_ptr, &sb) == 0) { + success = true; # ifndef TSRM_WIN32 /* * Try to set user and permission info on the target. @@ -1324,30 +1322,30 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f * on the system environment to have proper umask to not allow * access to the file in the meantime. */ - if (VCWD_CHOWN(url_to, sb.st_uid, sb.st_gid)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + if (VCWD_CHOWN(url_to_ptr, sb.st_uid, sb.st_gid)) { + php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); if (errno != EPERM) { - success = 0; + success = false; } } if (success) { - if (VCWD_CHMOD(url_to, sb.st_mode)) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + if (VCWD_CHMOD(url_to_ptr, sb.st_mode)) { + php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); if (errno != EPERM) { - success = 0; + success = false; } } } # endif if (success) { - VCWD_UNLINK(url_from); + VCWD_UNLINK(url_from_ptr); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); } } else { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); } # if !defined(ZTS) && !defined(TSRM_WIN32) umask(oldmask); @@ -1358,17 +1356,17 @@ static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_f #endif #ifdef PHP_WIN32 - php_win32_docref2_from_error(GetLastError(), url_from, url_to); + php_win32_docref2_from_error(GetLastError(), ZSTR_VAL(url_from), ZSTR_VAL(url_to)); #else - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); #endif - return 0; + return false; } /* Clear stat cache (and realpath cache) */ php_clear_stat_cache(1, NULL, 0); - return 1; + return true; } static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, int mode, int options, php_stream_context *context) diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 0bb80acf6b7c2..9c377cfe80e84 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -46,7 +46,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * static int user_wrapper_close(php_stream_wrapper *wrapper, php_stream *stream); static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context); static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); -static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context); +static bool user_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context); static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context); @@ -1067,7 +1067,7 @@ static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int return ret; } -static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, +static bool user_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; @@ -1084,8 +1084,8 @@ static int user_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from } /* call the rename method */ - ZVAL_STRING(&args[0], url_from); - ZVAL_STRING(&args[1], url_to); + ZVAL_STRINGL(&args[0], ZSTR_VAL(url_from), ZSTR_LEN(url_from)); + ZVAL_STRINGL(&args[1], ZSTR_VAL(url_to), ZSTR_LEN(url_to)); ZVAL_STRING(&zfuncname, USERSTREAM_RENAME); From 9048e85e958f5c1e6a60e6ac37f2b0ae92cf8ad0 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Wed, 21 Aug 2024 20:27:42 +0200 Subject: [PATCH 08/12] Zend: Refactor virtual_rmdir() to take path lengths --- Zend/zend_virtual_cwd.c | 13 ++++++------- Zend/zend_virtual_cwd.h | 16 ++++++++++------ main/streams/plain_wrapper.c | 5 +++-- win32/ioutil.c | 15 --------------- win32/ioutil.h | 18 ++++++++---------- 5 files changed, 27 insertions(+), 40 deletions(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index 4e2b98365275d..f5ccf8abe7122 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1618,22 +1618,21 @@ CWD_API int virtual_mkdir(const char *pathname, mode_t mode) /* {{{ */ } /* }}} */ -CWD_API int virtual_rmdir(const char *pathname) /* {{{ */ +CWD_API zend_result virtual_rmdir(const char *path, size_t path_length) /* {{{ */ { cwd_state new_state; - int retval; - size_t path_length = strlen(pathname); CWD_STATE_COPY(&new_state, &CWDG(cwd)); - if (virtual_file_ex(&new_state, pathname, path_length, NULL, CWD_EXPAND)) { + if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); - return -1; + return FAILURE; } + zend_result retval; #ifdef ZEND_WIN32 - retval = php_win32_ioutil_rmdir(new_state.cwd); + retval = php_win32_ioutil_rmdir(new_state.cwd, new_state.cwd_length); #else - retval = rmdir(new_state.cwd); + retval = virtual_rmdir_native(new_state.cwd, new_state.cwd_length); #endif CWD_STATE_FREE_ERR(&new_state); return retval; diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index f0d195254ee4c..347f3b06ca758 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -185,7 +185,7 @@ CWD_API int virtual_stat(const char *path, zend_stat_t *buf); CWD_API int virtual_lstat(const char *path, zend_stat_t *buf); CWD_API int virtual_unlink(const char *path); CWD_API int virtual_mkdir(const char *pathname, mode_t mode); -CWD_API int virtual_rmdir(const char *pathname); +CWD_API zend_result virtual_rmdir(const char *path, size_t path_len); CWD_API DIR *virtual_opendir(const char *pathname); CWD_API FILE *virtual_popen(const char *command, const char *type); CWD_API int virtual_access(const char *pathname, int mode); @@ -260,6 +260,10 @@ static zend_always_inline zend_result virtual_rename_native(const char *old_name return (rename(old_name, new_name) == 0) ? SUCCESS : FAILURE; } +static zend_always_inline zend_result virtual_rmdir_native(const char *path, ZEND_ATTRIBUTE_UNUSED size_t path_len) { + return (rmdir(path) == 0) ? SUCCESS : FAILURE; +} + #ifdef CWD_EXPORTS extern void virtual_cwd_main_cwd_init(uint8_t); #endif @@ -285,8 +289,8 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_STAT(path, buff) virtual_stat(path, buff) # define VCWD_LSTAT(path, buff) virtual_lstat(path, buff) #define VCWD_UNLINK(path) virtual_unlink(path) -#define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode) -#define VCWD_RMDIR(pathname) virtual_rmdir(pathname) +#define VCWD_MKDIR(path, mode) virtual_mkdir(path, mode) +#define VCWD_RMDIR(path, path_len) virtual_rmdir(path, path_len) #define VCWD_OPENDIR(pathname) virtual_opendir(pathname) #define VCWD_POPEN(command, type) virtual_popen(command, type) #define VCWD_ACCESS(pathname, mode) virtual_access(pathname, mode) @@ -311,8 +315,8 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_OPEN(path, flags) php_win32_ioutil_open(path, flags) #define VCWD_OPEN_MODE(path, flags, mode) php_win32_ioutil_open(path, flags, mode) #define VCWD_RENAME(old_name, old_name_length, new_name, new_name_length) php_win32_ioutil_rename(old_name, old_name_length, new_name, new_name_length) -#define VCWD_MKDIR(pathname, mode) php_win32_ioutil_mkdir(pathname, mode) -#define VCWD_RMDIR(pathname) php_win32_ioutil_rmdir(pathname) +#define VCWD_MKDIR(path, mode) php_win32_ioutil_mkdir(path, mode) +#define VCWD_RMDIR(path, path_length) php_win32_ioutil_rmdir(path, path_length) #define VCWD_UNLINK(path) php_win32_ioutil_unlink(path) #define VCWD_CHDIR(path) php_win32_ioutil_chdir(path) #define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode) @@ -324,7 +328,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_OPEN_MODE(path, flags, mode) open(path, flags, mode) #define VCWD_RENAME(old_name, old_name_len, new_name, new_name_len) virtual_rename_native(old_name, old_name_len, new_name, new_name_len) #define VCWD_MKDIR(path, mode) mkdir(path, mode) -#define VCWD_RMDIR(pathname) rmdir(pathname) +#define VCWD_RMDIR(path, path_len) virtual_rmdir_native(path, path_len) #define VCWD_UNLINK(path) unlink(path) #define VCWD_CHDIR(path) chdir(path) #define VCWD_ACCESS(pathname, mode) access(pathname, mode) diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 4fb905b9de427..a7491726123c6 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1471,14 +1471,15 @@ static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, i return 0; } + size_t url_len = strlen(url); #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url, strlen(url))) { + if (!php_win32_check_trailing_space(url, url_len)) { php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); return 0; } #endif - if (VCWD_RMDIR(url) < 0) { + if (VCWD_RMDIR(url, url_len) < 0) { php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); return 0; } diff --git a/win32/ioutil.c b/win32/ioutil.c index 8ba8cd1dc900b..29865d8402745 100644 --- a/win32/ioutil.c +++ b/win32/ioutil.c @@ -436,21 +436,6 @@ PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path) return 0; }/*}}}*/ -PW32IO int php_win32_ioutil_rmdir_w(const wchar_t *path) -{/*{{{*/ - int ret = 0; - - PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1, 0) - - if (!RemoveDirectoryW(path)) { - DWORD err = GetLastError(); - ret = -1; - SET_ERRNO_FROM_WIN32_CODE(err); - } - - return ret; -}/*}}}*/ - PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path) {/*{{{*/ int ret = 0; diff --git a/win32/ioutil.h b/win32/ioutil.h index 90f17d3ff5b98..fd538e427655b 100644 --- a/win32/ioutil.h +++ b/win32/ioutil.h @@ -359,30 +359,28 @@ __forceinline static int php_win32_ioutil_unlink(const char *path) return ret; }/*}}}*/ -__forceinline static int php_win32_ioutil_rmdir(const char *path) +__forceinline static zend_result php_win32_ioutil_rmdir(const char *path, size_t path_len) {/*{{{*/ + // TODO Is it possible to use php_win32_ioutil_conv_any_to_w() with path_len? PHP_WIN32_IOUTIL_INIT_W(path) - int ret = 0; DWORD err = 0; if (!pathw) { SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); - return -1; + return FAILURE; } - PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1, 1) + PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, FAILURE, 1) + zend_result ret = SUCCESS; if (!RemoveDirectoryW(pathw)) { - err = GetLastError(); - ret = -1; + DWORD err = GetLastError(); + SET_ERRNO_FROM_WIN32_CODE(err); + ret = FAILURE; } PHP_WIN32_IOUTIL_CLEANUP_W() - if (0 > ret) { - SET_ERRNO_FROM_WIN32_CODE(err); - } - return ret; }/*}}}*/ From d8f33a2f380059c04b0a9eecc28d840f609d1f44 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Thu, 22 Aug 2024 16:14:02 +0200 Subject: [PATCH 09/12] Add a CLEAN section --- ext/standard/tests/file/bug68335.phpt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ext/standard/tests/file/bug68335.phpt b/ext/standard/tests/file/bug68335.phpt index bb5f597fcaf71..3bbc71b8df27c 100644 --- a/ext/standard/tests/file/bug68335.phpt +++ b/ext/standard/tests/file/bug68335.phpt @@ -2,12 +2,17 @@ Bug #68335: rmdir doesn't work with file:// stream wrapper --FILE-- +--CLEAN-- + --EXPECT-- bool(true) bool(false) From 567d8b53ebe0893a413a7fc7fabeb52a2c21aca5 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Thu, 22 Aug 2024 16:14:28 +0200 Subject: [PATCH 10/12] streams: Refactor rmdir stream op to use zend_string --- ext/phar/dirstream.c | 14 +++++++------- ext/phar/dirstream.h | 2 +- ext/standard/file.c | 5 ++--- ext/standard/ftp_fopen_wrapper.c | 8 ++++---- main/php_streams.h | 4 ++-- main/streams/plain_wrapper.c | 30 ++++++++++++++++-------------- main/streams/streams.c | 6 +++--- main/streams/userspace.c | 6 +++--- 8 files changed, 38 insertions(+), 37 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 4674d868f4905..695a30fa4cb0b 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -526,7 +526,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo /** * Remove a directory within a phar archive */ -int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) /* {{{ */ +bool phar_wrapper_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) /* {{{ */ { phar_entry_info *entry; phar_archive_data *phar = NULL; @@ -539,8 +539,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options uint32_t path_len; /* pre-readonly check, we need to know if this is a data phar */ - if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, &entry2, &entry_len, 2, 2)) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url); + if (FAILURE == phar_split_fname(ZSTR_VAL(url), ZSTR_LEN(url), &arch, &arch_len, &entry2, &entry_len, 2, 2)) { + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", ZSTR_VAL(url)); return 0; } @@ -552,24 +552,24 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options efree(entry2); if (PHAR_G(readonly) && (!phar || !phar->is_data)) { - php_stream_wrapper_log_error(wrapper, options, "phar error: cannot rmdir directory \"%s\", write operations disabled", url); + php_stream_wrapper_log_error(wrapper, options, "phar error: cannot rmdir directory \"%s\", write operations disabled", ZSTR_VAL(url)); return 0; } - if ((resource = phar_parse_url(wrapper, url, "w", options)) == NULL) { + if ((resource = phar_parse_url(wrapper, ZSTR_VAL(url), "w", options)) == NULL) { return 0; } /* we must have at the very least phar://alias.phar/internalfile.php */ if (!resource->scheme || !resource->host || !resource->path) { php_url_free(resource); - php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", url); + php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", ZSTR_VAL(url)); return 0; } if (!zend_string_equals_literal_ci(resource->scheme, "phar")) { php_url_free(resource); - php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", url); + php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", ZSTR_VAL(url)); return 0; } diff --git a/ext/phar/dirstream.h b/ext/phar/dirstream.h index 4859c69fbe022..b0c07a015ec34 100644 --- a/ext/phar/dirstream.h +++ b/ext/phar/dirstream.h @@ -19,7 +19,7 @@ BEGIN_EXTERN_C() int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mode, int options, php_stream_context *context); -int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); +bool phar_wrapper_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); #ifdef PHAR_DIRSTREAM php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options); diff --git a/ext/standard/file.c b/ext/standard/file.c index e647176832096..9dcab7b80a5c8 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1160,13 +1160,12 @@ PHP_FUNCTION(mkdir) /* {{{ Remove a directory */ PHP_FUNCTION(rmdir) { - char *dir; - size_t dir_len; + zend_string *dir; zval *zcontext = NULL; php_stream_context *context; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_PATH(dir, dir_len) + Z_PARAM_PATH_STR(dir) Z_PARAM_OPTIONAL Z_PARAM_RESOURCE_OR_NULL(zcontext) ZEND_PARSE_PARAMETERS_END(); diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 44fb4395409f3..fd45e23ea8c92 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -1111,24 +1111,24 @@ static int php_stream_ftp_mkdir(php_stream_wrapper *wrapper, const char *url, in /* }}} */ /* {{{ php_stream_ftp_rmdir */ -static int php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) +static bool php_stream_ftp_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { php_stream *stream = NULL; php_url *resource = NULL; int result; char tmp_line[512]; - stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, context, NULL, &resource, NULL, NULL); + stream = php_ftp_fopen_connect(wrapper, ZSTR_VAL(url), "r", 0, NULL, context, NULL, &resource, NULL, NULL); if (!stream) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "Unable to connect to %s", url); + php_error_docref(NULL, E_WARNING, "Unable to connect to %s", ZSTR_VAL(url)); } goto rmdir_errexit; } if (resource->path == NULL) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "Invalid path provided in %s", url); + php_error_docref(NULL, E_WARNING, "Invalid path provided in %s", ZSTR_VAL(url)); } goto rmdir_errexit; } diff --git a/main/php_streams.h b/main/php_streams.h index f14a6cb1834b0..30df99be4d614 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -152,7 +152,7 @@ typedef struct _php_stream_wrapper_ops { /* Create/Remove directory */ int (*stream_mkdir)(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context); - int (*stream_rmdir)(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); + bool (*stream_rmdir)(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); /* Metadata handling */ int (*stream_metadata)(php_stream_wrapper *wrapper, const char *url, int options, void *value, php_stream_context *context); } php_stream_wrapper_ops; @@ -370,7 +370,7 @@ PHPAPI int _php_stream_stat_path(const char *path, int flags, php_stream_statbuf PHPAPI int _php_stream_mkdir(const char *path, int mode, int options, php_stream_context *context); #define php_stream_mkdir(path, mode, options, context) _php_stream_mkdir(path, mode, options, context) -PHPAPI int _php_stream_rmdir(const char *path, int options, php_stream_context *context); +PHPAPI bool _php_stream_rmdir(const zend_string *path, int options, php_stream_context *context); #define php_stream_rmdir(path, options, context) _php_stream_rmdir(path, options, context) PHPAPI php_stream *_php_stream_opendir(const char *path, int options, php_stream_context *context STREAMS_DC); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index a7491726123c6..8f7d4c6313260 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1461,33 +1461,35 @@ static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, i } } -static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) +static bool php_plain_files_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; + const char *url_ptr = ZSTR_VAL(url); + size_t url_len = ZSTR_LEN(url); + if (zend_string_starts_with_literal_ci(url, "file://")) { + url_ptr += strlen("file://"); + url_len -= strlen("file://"); } - if (php_check_open_basedir(url)) { - return 0; + if (php_check_open_basedir(url_ptr)) { + return false; } - size_t url_len = strlen(url); #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url, url_len)) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); - return 0; + if (!php_win32_check_trailing_space(url_ptr, url_len)) { + php_error_docref1(NULL, ZSTR_VAL(url), E_WARNING, "%s", strerror(ENOENT)); + return false; } #endif - if (VCWD_RMDIR(url, url_len) < 0) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); - return 0; + if (VCWD_RMDIR(url_ptr, url_len) < 0) { + php_error_docref1(NULL, ZSTR_VAL(url), E_WARNING, "%s", strerror(errno)); + return false; } /* Clear stat cache (and realpath cache) */ - php_clear_stat_cache(1, NULL, 0); + php_clear_stat_cache(true, NULL, 0); - return 1; + return true; } static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context) diff --git a/main/streams/streams.c b/main/streams/streams.c index f3fb5e3cda544..05d6928e5cbcf 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -2096,13 +2096,13 @@ PHPAPI int _php_stream_mkdir(const char *path, int mode, int options, php_stream /* }}} */ /* {{{ _php_stream_rmdir */ -PHPAPI int _php_stream_rmdir(const char *path, int options, php_stream_context *context) +PHPAPI bool _php_stream_rmdir(const zend_string *path, int options, php_stream_context *context) { php_stream_wrapper *wrapper = NULL; - wrapper = php_stream_locate_url_wrapper(path, NULL, 0); + wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(path), NULL, 0); if (!wrapper || !wrapper->wops || !wrapper->wops->stream_rmdir) { - return 0; + return false; } return wrapper->wops->stream_rmdir(wrapper, path, options, context); diff --git a/main/streams/userspace.c b/main/streams/userspace.c index 9c377cfe80e84..a433b0aa43b2a 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -48,7 +48,7 @@ static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, i static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); static bool user_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context); -static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); +static bool user_wrapper_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); static int user_wrapper_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context); static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC); @@ -1151,7 +1151,7 @@ static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int return ret; } -static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, +static bool user_wrapper_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; @@ -1168,7 +1168,7 @@ static int user_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, } /* call the rmdir method */ - ZVAL_STRING(&args[0], url); + ZVAL_STRINGL(&args[0], ZSTR_VAL(url), ZSTR_LEN(url)); ZVAL_LONG(&args[1], options); ZVAL_STRING(&zfuncname, USERSTREAM_RMDIR); From 947c4028a0e1f5fb7f1930485d1efe1260ffbc75 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Fri, 23 Aug 2024 16:02:42 +0200 Subject: [PATCH 11/12] Zend: Refactor virtual_unlink() to take path lengths --- Zend/zend_virtual_cwd.c | 11 +++++------ Zend/zend_virtual_cwd.h | 12 ++++++++---- ext/bz2/bz2.c | 2 +- ext/ftp/php_ftp.c | 34 ++++++++++++++++++---------------- ext/gd/gd.c | 2 +- ext/opcache/zend_file_cache.c | 24 ++++++++++++------------ ext/session/mod_files.c | 8 +++++--- ext/soap/php_sdl.c | 2 +- ext/standard/basic_functions.c | 2 +- main/rfc1867.c | 3 ++- main/streams/plain_wrapper.c | 11 +++++------ win32/ioutil.c | 14 +++++++------- win32/ioutil.h | 19 +++++++------------ 13 files changed, 73 insertions(+), 71 deletions(-) diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c index f5ccf8abe7122..76887fc304193 100644 --- a/Zend/zend_virtual_cwd.c +++ b/Zend/zend_virtual_cwd.c @@ -1573,22 +1573,21 @@ CWD_API int virtual_lstat(const char *path, zend_stat_t *buf) /* {{{ */ } /* }}} */ -CWD_API int virtual_unlink(const char *path) /* {{{ */ +CWD_API zend_result virtual_unlink(const char *path, size_t path_length) /* {{{ */ { cwd_state new_state; - int retval; - size_t path_length = strlen(path); + zend_result retval; CWD_STATE_COPY(&new_state, &CWDG(cwd)); if (virtual_file_ex(&new_state, path, path_length, NULL, CWD_EXPAND)) { CWD_STATE_FREE_ERR(&new_state); - return -1; + return FAILURE; } #ifdef ZEND_WIN32 - retval = php_win32_ioutil_unlink(new_state.cwd); + retval = php_win32_ioutil_unlink(new_state.cwd, new_state.cwd_length); #else - retval = unlink(new_state.cwd); + retval = virtual_unlink_native(new_state.cwd, new_state.cwd_length); #endif CWD_STATE_FREE_ERR(&new_state); diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h index 347f3b06ca758..d8e49f7371a8a 100644 --- a/Zend/zend_virtual_cwd.h +++ b/Zend/zend_virtual_cwd.h @@ -183,7 +183,7 @@ CWD_API int virtual_creat(const char *path, mode_t mode); CWD_API zend_result virtual_rename(const char *old_name, size_t old_name_len, const char *new_name, size_t new_name_len); CWD_API int virtual_stat(const char *path, zend_stat_t *buf); CWD_API int virtual_lstat(const char *path, zend_stat_t *buf); -CWD_API int virtual_unlink(const char *path); +CWD_API zend_result virtual_unlink(const char *path, size_t path_len); CWD_API int virtual_mkdir(const char *pathname, mode_t mode); CWD_API zend_result virtual_rmdir(const char *path, size_t path_len); CWD_API DIR *virtual_opendir(const char *pathname); @@ -260,6 +260,10 @@ static zend_always_inline zend_result virtual_rename_native(const char *old_name return (rename(old_name, new_name) == 0) ? SUCCESS : FAILURE; } +static zend_always_inline zend_result virtual_unlink_native(const char *path, ZEND_ATTRIBUTE_UNUSED size_t path_len) { + return (unlink(path) == 0) ? SUCCESS : FAILURE; +} + static zend_always_inline zend_result virtual_rmdir_native(const char *path, ZEND_ATTRIBUTE_UNUSED size_t path_len) { return (rmdir(path) == 0) ? SUCCESS : FAILURE; } @@ -288,7 +292,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_RENAME(old_name, old_name_length, new_name, new_name_length) virtual_rename(old_name, old_name_length, new_name, new_name_length) #define VCWD_STAT(path, buff) virtual_stat(path, buff) # define VCWD_LSTAT(path, buff) virtual_lstat(path, buff) -#define VCWD_UNLINK(path) virtual_unlink(path) +#define VCWD_UNLINK(path, path_len) virtual_unlink(path, path_len) #define VCWD_MKDIR(path, mode) virtual_mkdir(path, mode) #define VCWD_RMDIR(path, path_len) virtual_rmdir(path, path_len) #define VCWD_OPENDIR(pathname) virtual_opendir(pathname) @@ -317,7 +321,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_RENAME(old_name, old_name_length, new_name, new_name_length) php_win32_ioutil_rename(old_name, old_name_length, new_name, new_name_length) #define VCWD_MKDIR(path, mode) php_win32_ioutil_mkdir(path, mode) #define VCWD_RMDIR(path, path_length) php_win32_ioutil_rmdir(path, path_length) -#define VCWD_UNLINK(path) php_win32_ioutil_unlink(path) +#define VCWD_UNLINK(path, path_length) php_win32_ioutil_unlink(path, path_length) #define VCWD_CHDIR(path) php_win32_ioutil_chdir(path) #define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode) #define VCWD_GETCWD(buff, size) php_win32_ioutil_getcwd(buff, size) @@ -329,7 +333,7 @@ extern void virtual_cwd_main_cwd_init(uint8_t); #define VCWD_RENAME(old_name, old_name_len, new_name, new_name_len) virtual_rename_native(old_name, old_name_len, new_name, new_name_len) #define VCWD_MKDIR(path, mode) mkdir(path, mode) #define VCWD_RMDIR(path, path_len) virtual_rmdir_native(path, path_len) -#define VCWD_UNLINK(path) unlink(path) +#define VCWD_UNLINK(path, path_len) virtual_unlink_native(path, path_len) #define VCWD_CHDIR(path) chdir(path) #define VCWD_ACCESS(pathname, mode) access(pathname, mode) #define VCWD_GETCWD(buff, size) getcwd(buff, size) diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 86de6a5ca5f2d..071bc46fc623d 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -231,7 +231,7 @@ PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, * failed. */ if (opened_path && !bz_file && mode[0] == 'w') { - VCWD_UNLINK(ZSTR_VAL(*opened_path)); + VCWD_UNLINK(ZSTR_VAL(*opened_path), ZSTR_LEN(*opened_path)); } } diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 0336f9e953773..8eb0caa65d20a 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -682,11 +682,12 @@ PHP_FUNCTION(ftp_get) ftpbuf_t *ftp; ftptype_t xtype; php_stream *outstream; - char *local, *remote; - size_t local_len, remote_len; + zend_string *local; + char *remote; + size_t remote_len; zend_long mode=FTPTYPE_IMAGE, resumepos=0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Opp|ll", &z_ftp, php_ftp_ce, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "OPp|ll", &z_ftp, php_ftp_ce, &local, &remote, &remote_len, &mode, &resumepos) == FAILURE) { RETURN_THROWS(); } GET_FTPBUF(ftp, z_ftp); @@ -702,9 +703,9 @@ PHP_FUNCTION(ftp_get) #endif if (ftp->autoseek && resumepos) { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); if (outstream == NULL) { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream != NULL) { /* if autoresume is wanted seek to end */ @@ -716,17 +717,17 @@ PHP_FUNCTION(ftp_get) } } } else { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream == NULL) { - php_error_docref(NULL, E_WARNING, "Error opening %s", local); + php_error_docref(NULL, E_WARNING, "Error opening %s", ZSTR_VAL(local)); RETURN_FALSE; } if (!ftp_get(ftp, outstream, remote, remote_len, xtype, resumepos)) { php_stream_close(outstream); - VCWD_UNLINK(local); + VCWD_UNLINK(ZSTR_VAL(local), ZSTR_LEN(local)); if (*ftp->inbuf) { php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf); } @@ -745,12 +746,13 @@ PHP_FUNCTION(ftp_nb_get) ftpbuf_t *ftp; ftptype_t xtype; php_stream *outstream; - char *local, *remote; - size_t local_len, remote_len; + zend_string *local; + char *remote; + size_t remote_len; int ret; zend_long mode=FTPTYPE_IMAGE, resumepos=0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss|ll", &z_ftp, php_ftp_ce, &local, &local_len, &remote, &remote_len, &mode, &resumepos) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSs|ll", &z_ftp, php_ftp_ce, &local, &remote, &remote_len, &mode, &resumepos) == FAILURE) { RETURN_THROWS(); } GET_FTPBUF(ftp, z_ftp); @@ -764,9 +766,9 @@ PHP_FUNCTION(ftp_nb_get) mode = FTPTYPE_IMAGE; #endif if (ftp->autoseek && resumepos) { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "rt+" : "rb+", REPORT_ERRORS, NULL); if (outstream == NULL) { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream != NULL) { /* if autoresume is wanted seek to end */ @@ -778,11 +780,11 @@ PHP_FUNCTION(ftp_nb_get) } } } else { - outstream = php_stream_open_wrapper(local, mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); + outstream = php_stream_open_wrapper(ZSTR_VAL(local), mode == FTPTYPE_ASCII ? "wt" : "wb", REPORT_ERRORS, NULL); } if (outstream == NULL) { - php_error_docref(NULL, E_WARNING, "Error opening %s", local); + php_error_docref(NULL, E_WARNING, "Error opening %s", ZSTR_VAL(local)); RETURN_FALSE; } @@ -793,7 +795,7 @@ PHP_FUNCTION(ftp_nb_get) if ((ret = ftp_nb_get(ftp, outstream, remote, remote_len, xtype, resumepos)) == PHP_FTP_FAILED) { php_stream_close(outstream); ftp->stream = NULL; - VCWD_UNLINK(local); + VCWD_UNLINK(ZSTR_VAL(local), ZSTR_LEN(local)); if (*ftp->inbuf) { php_error_docref(NULL, E_WARNING, "%s", ftp->inbuf); } diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 899dc05b3e829..41d670622dca3 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -1847,7 +1847,7 @@ static void _php_image_output(INTERNAL_FUNCTION_PARAMETERS, int image_type, cons } fclose(tmp); - VCWD_UNLINK((const char *)ZSTR_VAL(path)); /* make sure that the temporary file is removed */ + VCWD_UNLINK(ZSTR_VAL(path), ZSTR_LEN(path)); /* make sure that the temporary file is removed */ zend_string_release_ex(path, 0); } RETURN_TRUE; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 736d644516a04..dff028f390417 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -62,7 +62,7 @@ #endif #ifndef ZEND_WIN32 -#define zend_file_cache_unlink unlink +#define zend_file_cache_unlink virtual_unlink_native #define zend_file_cache_open open #else #define zend_file_cache_unlink php_win32_ioutil_unlink @@ -1161,7 +1161,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, bool in_shm) zend_string_release_ex(s, 0); close(fd); efree(mem); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, strlen(filename)); efree(filename); return FAILURE; } @@ -1826,6 +1826,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl return NULL; } filename = zend_file_cache_get_bin_file_path(full_path); + size_t filename_len = strlen(filename); fd = zend_file_cache_open(filename, O_RDONLY | O_BINARY); if (fd < 0) { @@ -1843,7 +1844,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (info)\n", filename); zend_file_cache_flock(fd, LOCK_UN); close(fd); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); efree(filename); return NULL; } @@ -1853,7 +1854,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong header)\n", filename); zend_file_cache_flock(fd, LOCK_UN); close(fd); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); efree(filename); return NULL; } @@ -1861,7 +1862,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename); zend_file_cache_flock(fd, LOCK_UN); close(fd); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); efree(filename); return NULL; } @@ -1873,7 +1874,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot unlock file '%s'\n", filename); } close(fd); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); efree(filename); return NULL; } @@ -1891,7 +1892,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (mem)\n", filename); zend_file_cache_flock(fd, LOCK_UN); close(fd); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); zend_arena_release(&CG(arena), checkpoint); efree(filename); return NULL; @@ -1905,7 +1906,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl if (ZCG(accel_directives).file_cache_consistency_checks && (actual_checksum = zend_adler32(ADLER32_INIT, mem, info.mem_size + info.str_size)) != info.checksum) { zend_accel_error(ACCEL_LOG_WARNING, "corrupted file '%s' excepted checksum: 0x%08x actual checksum: 0x%08x\n", filename, info.checksum, actual_checksum); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); zend_arena_release(&CG(arena), checkpoint); efree(filename); return NULL; @@ -1997,10 +1998,9 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl void zend_file_cache_invalidate(zend_string *full_path) { - char *filename; - - filename = zend_file_cache_get_bin_file_path(full_path); + char *filename = zend_file_cache_get_bin_file_path(full_path); + size_t filename_len = strlen(filename); - zend_file_cache_unlink(filename); + zend_file_cache_unlink(filename, filename_len); efree(filename); } diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 74e77973405b2..7ca311bf2697e 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -315,12 +315,13 @@ static int ps_files_cleanup_dir(const zend_string *dirname, zend_long maxlifetim memcpy(buf + ZSTR_LEN(dirname) + 1, entry->d_name, entry_len); /* NUL terminate it and */ - buf[ZSTR_LEN(dirname) + entry_len + 1] = '\0'; + size_t buf_len = ZSTR_LEN(dirname) + entry_len + 1; + buf[buf_len] = '\0'; /* check whether its last access was more than maxlifetime ago */ if (VCWD_STAT(buf, &sbuf) == 0 && (now - sbuf.st_mtime) > maxlifetime) { - VCWD_UNLINK(buf); + VCWD_UNLINK(buf, buf_len); nrdels++; } } @@ -602,7 +603,8 @@ PS_DESTROY_FUNC(files) if (data->fd != -1) { ps_files_close(data); - if (VCWD_UNLINK(buf) == -1) { + size_t buf_len = strlen(buf); + if (VCWD_UNLINK(buf, buf_len) == FAILURE) { /* This is a little safety check for instances when we are dealing with a regenerated session * that was not yet written to disk. */ if (!VCWD_ACCESS(buf, F_OK)) { diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c index c78ca3214fea5..c6bae2f854a6d 100644 --- a/ext/soap/php_sdl.c +++ b/ext/soap/php_sdl.c @@ -2364,7 +2364,7 @@ static void add_sdl_to_cache(const char *fn, size_t fn_len, const char *uri, tim if (valid_file) { /* This is allowed to fail, this means that another process was raced to create the file. */ if (VCWD_RENAME(ZSTR_VAL(temp_file_path), ZSTR_LEN(temp_file_path), fn, fn_len) < 0) { - VCWD_UNLINK(ZSTR_VAL(temp_file_path)); + VCWD_UNLINK(ZSTR_VAL(temp_file_path), ZSTR_LEN(temp_file_path)); } } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 752fa9ab46232..f85b8481a9682 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2393,7 +2393,7 @@ PHP_FUNCTION(move_uploaded_file) } #endif } else if (php_copy_file_ex(ZSTR_VAL(path), new_path, STREAM_DISABLE_OPEN_BASEDIR) == SUCCESS) { - VCWD_UNLINK(ZSTR_VAL(path)); + VCWD_UNLINK(ZSTR_VAL(path), ZSTR_LEN(path)); successful = 1; } diff --git a/main/rfc1867.c b/main/rfc1867.c index 3ba78f7382191..afa75ee7b1e26 100644 --- a/main/rfc1867.c +++ b/main/rfc1867.c @@ -171,7 +171,7 @@ PHPAPI void destroy_uploaded_files_hash(void) /* {{{ */ ZEND_HASH_MAP_FOREACH_VAL(SG(rfc1867_uploaded_files), el) { zend_string *filename = Z_STR_P(el); - VCWD_UNLINK(ZSTR_VAL(filename)); + VCWD_UNLINK(ZSTR_VAL(filename), ZSTR_LEN(filename)); } ZEND_HASH_FOREACH_END(); zend_hash_destroy(SG(rfc1867_uploaded_files)); FREE_HASHTABLE(SG(rfc1867_uploaded_files)); @@ -1089,6 +1089,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) if (cancel_upload) { if (temp_filename) { if (cancel_upload != PHP_UPLOAD_ERROR_E) { /* file creation failed */ + // TODO Should this use VCWD_UNLINK()? unlink(ZSTR_VAL(temp_filename)); } zend_string_release_ex(temp_filename, 0); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 8f7d4c6313260..c63d02333e3b9 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -509,7 +509,7 @@ static int php_stdiop_close(php_stream *stream, int close_handle) } if (data->temp_name) { #ifdef PHP_WIN32 - php_win32_ioutil_unlink(ZSTR_VAL(data->temp_name)); + php_win32_ioutil_unlink(ZSTR_VAL(data->temp_name), ZSTR_LEN(data->temp_name)); #else unlink(ZSTR_VAL(data->temp_name)); #endif @@ -1242,8 +1242,6 @@ static int php_plain_files_url_stater(php_stream_wrapper *wrapper, const char *u static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) { - int ret; - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { url += sizeof("file://") - 1; } @@ -1252,8 +1250,9 @@ static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, return 0; } - ret = VCWD_UNLINK(url); - if (ret == -1) { + size_t url_len = strlen(url); + zend_result ret = VCWD_UNLINK(url, url_len); + if (ret == FAILURE) { if (options & REPORT_ERRORS) { php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); } @@ -1339,7 +1338,7 @@ static bool php_plain_files_rename(php_stream_wrapper *wrapper, const zend_strin } # endif if (success) { - VCWD_UNLINK(url_from_ptr); + VCWD_UNLINK(url_from_ptr, url_from_len); } } else { php_error_docref2(NULL, ZSTR_VAL(url_from), ZSTR_VAL(url_to), E_WARNING, "%s", strerror(errno)); diff --git a/win32/ioutil.c b/win32/ioutil.c index 29865d8402745..11414b4d5f092 100644 --- a/win32/ioutil.c +++ b/win32/ioutil.c @@ -365,7 +365,7 @@ PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode) return 0; }/*}}}*/ -PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path) +PW32IO zend_result php_win32_ioutil_unlink_w(const wchar_t *path) {/*{{{*/ DWORD err = 0; HANDLE h; @@ -373,7 +373,7 @@ PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path) FILE_DISPOSITION_INFO disposition; BOOL status; - PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1, 0) + PHP_WIN32_IOUTIL_CHECK_PATH_W(path, FAILURE, 0) h = CreateFileW(path, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | DELETE, @@ -386,21 +386,21 @@ PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path) if (INVALID_HANDLE_VALUE == h) { err = GetLastError(); SET_ERRNO_FROM_WIN32_CODE(err); - return -1; + return FAILURE; } if (!GetFileInformationByHandle(h, &info)) { err = GetLastError(); CloseHandle(h); SET_ERRNO_FROM_WIN32_CODE(err); - return -1; + return FAILURE; } if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { /* TODO Handle possible reparse point. */ CloseHandle(h); SET_ERRNO_FROM_WIN32_CODE(ERROR_DIRECTORY_NOT_SUPPORTED); - return -1; + return FAILURE; } #if 0 @@ -428,12 +428,12 @@ PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path) err = GetLastError(); CloseHandle(h); SET_ERRNO_FROM_WIN32_CODE(err); - return -1; + return FAILURE; } CloseHandle(h); - return 0; + return SUCCESS; }/*}}}*/ PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path) diff --git a/win32/ioutil.h b/win32/ioutil.h index fd538e427655b..6ddf7352a6655 100644 --- a/win32/ioutil.h +++ b/win32/ioutil.h @@ -266,7 +266,7 @@ PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...); PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path); PW32IO zend_result php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname); PW32IO wchar_t *php_win32_ioutil_getcwd_w(wchar_t *buf, size_t len); -PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path); +PW32IO zend_result php_win32_ioutil_unlink_w(const wchar_t *path); PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode); PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode); PW32IO FILE *php_win32_ioutil_fopen_w(const wchar_t *path, const wchar_t *mode); @@ -335,26 +335,21 @@ __forceinline static int php_win32_ioutil_open(const char *path, int flags, ...) return ret; }/*}}}*/ -__forceinline static int php_win32_ioutil_unlink(const char *path) +__forceinline static zend_result php_win32_ioutil_unlink(const char *path, size_t path_len) {/*{{{*/ PHP_WIN32_IOUTIL_INIT_W(path) - int ret = -1; - DWORD err; if (!pathw) { SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER); - return -1; - } - - ret = php_win32_ioutil_unlink_w(pathw); - if (0 > ret) { - err = GetLastError(); + return FAILURE; } - PHP_WIN32_IOUTIL_CLEANUP_W() - if (0 > ret) { + zend_result ret = php_win32_ioutil_unlink_w(pathw); + if (ret == FAILURE) { + DWORD err = GetLastError(); SET_ERRNO_FROM_WIN32_CODE(err); } + PHP_WIN32_IOUTIL_CLEANUP_W() return ret; }/*}}}*/ From 5194bd969d1cb41b4b73ac73e4dfa8df209c9181 Mon Sep 17 00:00:00 2001 From: Gina Peter Bnayard Date: Fri, 23 Aug 2024 16:25:55 +0200 Subject: [PATCH 12/12] streams: Refactor unlink stream op to use zend_string --- ext/phar/stream.c | 24 ++++++++++++------------ ext/phar/stream.h | 2 +- ext/standard/file.c | 7 +++---- ext/standard/ftp_fopen_wrapper.c | 12 ++++++------ main/php_streams.h | 2 +- main/streams/plain_wrapper.c | 22 ++++++++++++---------- main/streams/userspace.c | 13 ++++++------- 7 files changed, 41 insertions(+), 41 deletions(-) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 9da615e752088..ab438196255e5 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -667,7 +667,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f /** * Unlink a file within a phar archive */ -static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) /* {{{ */ +static bool phar_wrapper_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) /* {{{ */ { php_url *resource; char *internal_file, *error; @@ -676,22 +676,22 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int phar_archive_data *pphar; uint32_t host_len; - if ((resource = phar_parse_url(wrapper, url, "rb", options)) == NULL) { + if ((resource = phar_parse_url(wrapper, ZSTR_VAL(url), "rb", options)) == NULL) { php_stream_wrapper_log_error(wrapper, options, "phar error: unlink failed"); - return 0; + return false; } /* we must have at the very least phar://alias.phar/internalfile.php */ if (!resource->scheme || !resource->host || !resource->path) { php_url_free(resource); - php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", url); - return 0; + php_stream_wrapper_log_error(wrapper, options, "phar error: invalid url \"%s\"", ZSTR_VAL(url)); + return false; } if (!zend_string_equals_literal_ci(resource->scheme, "phar")) { php_url_free(resource); - php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", url); - return 0; + php_stream_wrapper_log_error(wrapper, options, "phar error: not a phar stream url \"%s\"", ZSTR_VAL(url)); + return false; } host_len = ZSTR_LEN(resource->host); @@ -710,14 +710,14 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int if (FAILURE == phar_get_entry_data(&idata, ZSTR_VAL(resource->host), host_len, internal_file, internal_file_len, "r", 0, &error, 1)) { /* constraints of fp refcount were not met */ if (error) { - php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed: %s", url, error); + php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed: %s", ZSTR_VAL(url), error); efree(error); } else { - php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed, file does not exist", url); + php_stream_wrapper_log_error(wrapper, options, "unlink of \"%s\" failed, file does not exist", ZSTR_VAL(url)); } efree(internal_file); php_url_free(resource); - return 0; + return false; } if (error) { efree(error); @@ -728,7 +728,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int efree(internal_file); php_url_free(resource); phar_entry_delref(idata); - return 0; + return false; } php_url_free(resource); efree(internal_file); @@ -737,7 +737,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int php_stream_wrapper_log_error(wrapper, options, "%s", error); efree(error); } - return 1; + return true; } /* }}} */ diff --git a/ext/phar/stream.h b/ext/phar/stream.h index ae76eb9b57093..6c38dafabed40 100644 --- a/ext/phar/stream.h +++ b/ext/phar/stream.h @@ -24,7 +24,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error); static php_stream* phar_wrapper_open_url(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC); static bool phar_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); -static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); +static bool phar_wrapper_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context); /* file/stream handlers */ diff --git a/ext/standard/file.c b/ext/standard/file.c index 9dcab7b80a5c8..941afac110d8b 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -1294,21 +1294,20 @@ PHP_FUNCTION(rename) /* {{{ Delete a file */ PHP_FUNCTION(unlink) { - char *filename; - size_t filename_len; + zend_string *filename; php_stream_wrapper *wrapper; zval *zcontext = NULL; php_stream_context *context = NULL; ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_PATH(filename, filename_len) + Z_PARAM_PATH_STR(filename) Z_PARAM_OPTIONAL Z_PARAM_RESOURCE_OR_NULL(zcontext) ZEND_PARSE_PARAMETERS_END(); context = php_stream_context_from_zval(zcontext, 0); - wrapper = php_stream_locate_url_wrapper(filename, NULL, 0); + wrapper = php_stream_locate_url_wrapper(ZSTR_VAL(filename), NULL, 0); if (!wrapper || !wrapper->wops) { php_error_docref(NULL, E_WARNING, "Unable to locate stream wrapper"); diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index fd45e23ea8c92..be5ccc9584229 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -892,24 +892,24 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, /* }}} */ /* {{{ php_stream_ftp_unlink */ -static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) +static bool php_stream_ftp_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { php_stream *stream = NULL; php_url *resource = NULL; int result; char tmp_line[512]; - stream = php_ftp_fopen_connect(wrapper, url, "r", 0, NULL, context, NULL, &resource, NULL, NULL); + stream = php_ftp_fopen_connect(wrapper, ZSTR_VAL(url), "r", 0, NULL, context, NULL, &resource, NULL, NULL); if (!stream) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "Unable to connect to %s", url); + php_error_docref(NULL, E_WARNING, "Unable to connect to %s", ZSTR_VAL(url)); } goto unlink_errexit; } if (resource->path == NULL) { if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "Invalid path provided in %s", url); + php_error_docref(NULL, E_WARNING, "Invalid path provided in %s", ZSTR_VAL(url)); } goto unlink_errexit; } @@ -927,7 +927,7 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i php_url_free(resource); php_stream_close(stream); - return 1; + return true; unlink_errexit: if (resource) { @@ -936,7 +936,7 @@ static int php_stream_ftp_unlink(php_stream_wrapper *wrapper, const char *url, i if (stream) { php_stream_close(stream); } - return 0; + return false; } /* }}} */ diff --git a/main/php_streams.h b/main/php_streams.h index 30df99be4d614..34239e747299b 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -145,7 +145,7 @@ typedef struct _php_stream_wrapper_ops { const char *label; /* delete a file */ - int (*unlink)(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); + bool (*unlink)(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); /* rename a file */ bool (*rename)(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index c63d02333e3b9..8aa8994934704 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -1240,29 +1240,31 @@ static int php_plain_files_url_stater(php_stream_wrapper *wrapper, const char *u return VCWD_STAT(url, &ssb->sb); } -static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) +static bool php_plain_files_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; + const char *url_ptr = ZSTR_VAL(url); + size_t url_len = ZSTR_LEN(url); + if (zend_string_starts_with_literal_ci(url, "file://")) { + url_ptr += strlen("file://"); + url_len -= strlen("file://"); } - if (php_check_open_basedir(url)) { - return 0; + if (php_check_open_basedir(ZSTR_VAL(url))) { + return false; } - size_t url_len = strlen(url); - zend_result ret = VCWD_UNLINK(url, url_len); + zend_result ret = VCWD_UNLINK(url_ptr, url_len); if (ret == FAILURE) { if (options & REPORT_ERRORS) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + php_error_docref1(NULL, ZSTR_VAL(url), E_WARNING, "%s", strerror(errno)); } - return 0; + return false; } /* Clear stat cache (and realpath cache) */ php_clear_stat_cache(1, NULL, 0); - return 1; + return true; } static bool php_plain_files_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context) diff --git a/main/streams/userspace.c b/main/streams/userspace.c index a433b0aa43b2a..cb7559d28787b 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -45,7 +45,7 @@ struct php_user_stream_wrapper { static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC); static int user_wrapper_close(php_stream_wrapper *wrapper, php_stream *stream); static int user_wrapper_stat_url(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context); -static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context); +static bool user_wrapper_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); static bool user_wrapper_rename(php_stream_wrapper *wrapper, const zend_string *url_from, const zend_string *url_to, int options, php_stream_context *context); static int user_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url, int mode, int options, php_stream_context *context); static bool user_wrapper_rmdir(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context); @@ -1029,28 +1029,27 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value } -static int user_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) +static bool user_wrapper_unlink(php_stream_wrapper *wrapper, const zend_string *url, int options, php_stream_context *context) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; zval zfuncname, zretval; zval args[1]; - int call_result; zval object; - int ret = 0; /* create an instance of our class */ user_stream_create_object(uwrap, context, &object); if (Z_TYPE(object) == IS_UNDEF) { - return ret; + return false; } /* call the unlink method */ - ZVAL_STRING(&args[0], url); + ZVAL_STRINGL(&args[0], ZSTR_VAL(url), ZSTR_LEN(url)); ZVAL_STRING(&zfuncname, USERSTREAM_UNLINK); - call_result = call_method_if_exists(&object, &zfuncname, &zretval, 1, args); + zend_result call_result = call_method_if_exists(&object, &zfuncname, &zretval, 1, args); + bool ret = false; if (call_result == SUCCESS && (Z_TYPE(zretval) == IS_FALSE || Z_TYPE(zretval) == IS_TRUE)) { ret = (Z_TYPE(zretval) == IS_TRUE); } else if (call_result == FAILURE) {