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

ext/phar/phar_object.c: Refactor extraction code to use zend_string*

This commit is contained in:
Gina Peter Banyard
2025-10-13 16:11:52 +01:00
parent bf44b6ec4e
commit 264d650117

View File

@@ -4108,7 +4108,7 @@ PHP_METHOD(Phar, delMetadata)
}
/* }}} */
static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, char *dest, size_t dest_len, char **error) /* {{{ */
static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, const zend_string *path, char **error) /* {{{ */
{
php_stream_statbuf ssb;
size_t len;
@@ -4136,7 +4136,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha
if (virtual_file_ex(&new_state, ZSTR_VAL(entry->filename), NULL, CWD_EXPAND) != 0 ||
new_state.cwd_length <= 1) {
if (EINVAL == errno && ZSTR_LEN(entry->filename) > 50) {
spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), dest);
spprintf(error, 4096, "Cannot extract \"%.50s...\" to \"%s...\", extracted filename is too long for filesystem", ZSTR_VAL(entry->filename), ZSTR_VAL(path));
} else {
spprintf(error, 4096, "Cannot extract \"%s\", internal error", ZSTR_VAL(entry->filename));
}
@@ -4158,7 +4158,7 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha
}
#endif
len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
len = spprintf(&fullpath, 0, "%s/%s", ZSTR_VAL(path), filename);
if (len >= MAXPATHLEN) {
/* truncate for error message */
@@ -4199,9 +4199,9 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha
slash = zend_memrchr(filename, '/', filename_len);
if (slash) {
fullpath[dest_len + (slash - filename) + 1] = '\0';
fullpath[ZSTR_LEN(path) + (slash - filename) + 1] = '\0';
} else {
fullpath[dest_len] = '\0';
fullpath[ZSTR_LEN(path)] = '\0';
}
if (FAILURE == php_stream_stat_path(fullpath, &ssb)) {
@@ -4223,9 +4223,9 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha
}
if (slash) {
fullpath[dest_len + (slash - filename) + 1] = '/';
fullpath[ZSTR_LEN(path) + (slash - filename) + 1] = '/';
} else {
fullpath[dest_len] = '/';
fullpath[ZSTR_LEN(path)] = '/';
}
filename = NULL;
@@ -4285,28 +4285,28 @@ static zend_result phar_extract_file(bool overwrite, phar_entry_info *entry, cha
}
/* }}} */
static int extract_helper(phar_archive_data *archive, zend_string *search, char *pathto, size_t pathto_len, bool overwrite, char **error) { /* {{{ */
static int extract_helper(const phar_archive_data *archive, zend_string *search, const zend_string *path_to, bool overwrite, char **error) { /* {{{ */
int extracted = 0;
phar_entry_info *entry;
if (!search) {
/* nothing to match -- extract all files */
ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) {
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1;
extracted++;
} ZEND_HASH_FOREACH_END();
} else if (ZSTR_LEN(search) > 0 && '/' == ZSTR_VAL(search)[ZSTR_LEN(search) - 1]) {
/* ends in "/" -- extract all entries having that prefix */
ZEND_HASH_MAP_FOREACH_PTR(&archive->manifest, entry) {
if (!zend_string_starts_with(entry->filename, search)) continue;
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1;
extracted++;
} ZEND_HASH_FOREACH_END();
} else {
/* otherwise, looking for an exact match */
entry = zend_hash_find_ptr(&archive->manifest, search);
if (NULL == entry) return 0;
if (FAILURE == phar_extract_file(overwrite, entry, pathto, pathto_len, error)) return -1;
if (FAILURE == phar_extract_file(overwrite, entry, path_to, error)) return -1;
return 1;
}
@@ -4319,9 +4319,8 @@ PHP_METHOD(Phar, extractTo)
{
php_stream *fp;
php_stream_statbuf ssb;
char *pathto;
zend_string *path_to;
zend_string *filename = NULL;
size_t pathto_len;
int ret;
zval *zval_file;
HashTable *files_ht = NULL;
@@ -4329,7 +4328,7 @@ PHP_METHOD(Phar, extractTo)
char *error = NULL;
ZEND_PARSE_PARAMETERS_START(1, 3)
Z_PARAM_PATH(pathto, pathto_len)
Z_PARAM_PATH_STR(path_to)
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY_HT_OR_STR_OR_NULL(files_ht, filename)
Z_PARAM_BOOL(overwrite)
@@ -4347,30 +4346,30 @@ PHP_METHOD(Phar, extractTo)
php_stream_close(fp);
if (pathto_len < 1) {
if (ZSTR_LEN(path_to) == 0) {
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
"Invalid argument, extraction path must be non-zero length");
RETURN_THROWS();
}
if (pathto_len >= MAXPATHLEN) {
char *tmp = estrndup(pathto, 50);
if (ZSTR_LEN(path_to) >= MAXPATHLEN) {
char *tmp = estrndup(ZSTR_VAL(path_to), 50);
/* truncate for error message */
zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Cannot extract to \"%s...\", destination directory is too long for filesystem", tmp);
efree(tmp);
RETURN_THROWS();
}
if (php_stream_stat_path(pathto, &ssb) < 0) {
ret = php_stream_mkdir(pathto, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
if (php_stream_stat_path(ZSTR_VAL(path_to), &ssb) < 0) {
ret = php_stream_mkdir(ZSTR_VAL(path_to), 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL);
if (!ret) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0,
"Unable to create path \"%s\" for extraction", pathto);
"Unable to create path \"%s\" for extraction", ZSTR_VAL(path_to));
RETURN_THROWS();
}
} else if (!(ssb.sb.st_mode & S_IFDIR)) {
zend_throw_exception_ex(spl_ce_RuntimeException, 0,
"Unable to use path \"%s\" for extraction, it is a file, must be a directory", pathto);
"Unable to use path \"%s\" for extraction, it is a file, must be a directory", ZSTR_VAL(path_to));
RETURN_THROWS();
}
@@ -4386,7 +4385,7 @@ PHP_METHOD(Phar, extractTo)
"Invalid argument, array of filenames to extract contains non-string value");
RETURN_THROWS();
}
switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), pathto, pathto_len, overwrite, &error)) {
switch (extract_helper(phar_obj->archive, Z_STR_P(zval_file), path_to, overwrite, &error)) {
case -1:
zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
phar_obj->archive->fname, error);
@@ -4402,7 +4401,7 @@ PHP_METHOD(Phar, extractTo)
RETURN_TRUE;
}
ret = extract_helper(phar_obj->archive, filename, pathto, pathto_len, overwrite, &error);
ret = extract_helper(phar_obj->archive, filename, path_to, overwrite, &error);
if (-1 == ret) {
zend_throw_exception_ex(phar_ce_PharException, 0, "Extraction from phar \"%s\" failed: %s",
phar_obj->archive->fname, error);