Skip to content

Commit e2a9232

Browse files
authored
ext/phar: use zend_string for entry in phar_split_fname() (#21767)
This saves us to do multiple reallocations from zend_string* to char* back to a zend_string*.
1 parent 4997418 commit e2a9232

File tree

7 files changed

+46
-49
lines changed

7 files changed

+46
-49
lines changed

ext/phar/dirstream.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo
350350
php_url *resource = NULL;
351351

352352
/* pre-readonly check, we need to know if this is a data phar */
353-
if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, NULL, 2, 2)) {
353+
if (FAILURE == phar_split_fname(url_from, strlen(url_from), &arch, &arch_len, NULL, 2, 2)) {
354354
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\", no phar archive specified", url_from);
355355
return 0;
356356
}
@@ -476,7 +476,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options
476476
php_url *resource = NULL;
477477

478478
/* pre-readonly check, we need to know if this is a data phar */
479-
if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, NULL, 2, 2)) {
479+
if (FAILURE == phar_split_fname(url, strlen(url), &arch, &arch_len, NULL, 2, 2)) {
480480
php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\", no phar archive specified, or phar archive does not exist", url);
481481
return 0;
482482
}

ext/phar/func_interceptors.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PHP_FUNCTION(phar_opendir) /* {{{ */
4848
goto skip_phar;
4949
}
5050

51-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) {
51+
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
5252
php_stream_context *context = NULL;
5353
php_stream *stream;
5454
char *name;
@@ -94,7 +94,7 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool
9494
return NULL;
9595
}
9696

97-
if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) {
97+
if (FAILURE == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
9898
return NULL;
9999
}
100100

@@ -496,7 +496,7 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ
496496
phar = PHAR_G(last_phar);
497497
goto splitted;
498498
}
499-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) {
499+
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
500500
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
501501
if (FAILURE == phar_get_archive(&phar, arch, arch_len, NULL, 0, NULL)) {
502502
efree(arch);
@@ -737,7 +737,7 @@ PHP_FUNCTION(phar_is_file) /* {{{ */
737737
goto skip_phar;
738738
}
739739

740-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) {
740+
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
741741
phar_archive_data *phar;
742742

743743
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */
@@ -795,7 +795,7 @@ PHP_FUNCTION(phar_is_link) /* {{{ */
795795
goto skip_phar;
796796
}
797797

798-
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)) {
798+
if (SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)) {
799799
phar_archive_data *phar;
800800

801801
/* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */

ext/phar/phar.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,7 @@ zend_string* phar_fix_filepath(const char *path, size_t path_length, bool use_cw
21632163
*
21642164
* This is used by phar_parse_url()
21652165
*/
2166-
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create) /* {{{ */
2166+
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, zend_string **entry, int executable, int for_create) /* {{{ */
21672167
{
21682168
const char *ext_str;
21692169
#ifdef PHP_WIN32
@@ -2219,13 +2219,9 @@ zend_result phar_split_fname(const char *filename, size_t filename_len, char **a
22192219
size_t computed_entry_len = filename_len - *arch_len;
22202220
/* We don't need to unixify the path on Windows,
22212221
* as ext_str is derived from filename that was already unixify */
2222-
zend_string *entry_str = phar_fix_filepath(ext_str+ext_len, computed_entry_len, false);
2223-
*entry = estrndup(ZSTR_VAL(entry_str), ZSTR_LEN(entry_str));
2224-
*entry_len = ZSTR_LEN(entry_str);
2225-
zend_string_release_ex(entry_str, false);
2222+
*entry = phar_fix_filepath(ext_str+ext_len, computed_entry_len, false);
22262223
} else {
2227-
*entry_len = 1;
2228-
*entry = estrndup("/", 1);
2224+
*entry = ZSTR_CHAR('/');
22292225
}
22302226
}
22312227

ext/phar/phar_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, ch
474474
ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error);
475475
ZEND_ATTRIBUTE_NONNULL int phar_flush(phar_archive_data *archive, char **error);
476476
zend_result phar_detect_phar_fname_ext(const char *filename, size_t filename_len, const char **ext_str, size_t *ext_len, int executable, int for_create, bool is_complete);
477-
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, char **entry, size_t *entry_len, int executable, int for_create);
477+
zend_result phar_split_fname(const char *filename, size_t filename_len, char **arch, size_t *arch_len, zend_string **entry, int executable, int for_create);
478478

479479
typedef enum {
480480
pcr_use_query,

ext/phar/phar_object.c

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ PHP_METHOD(Phar, running)
419419

420420
if (
421421
zend_string_starts_with_literal_ci(fname, "phar://")
422-
&& SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 2, 0)
422+
&& SUCCESS == phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 2, 0)
423423
) {
424424
if (retphar) {
425425
RETVAL_STRINGL(ZSTR_VAL(fname), arch_len + 7);
@@ -444,8 +444,8 @@ PHP_METHOD(Phar, running)
444444
*/
445445
PHP_METHOD(Phar, mount)
446446
{
447-
char *fname, *arch = NULL, *entry = NULL, *path, *actual;
448-
size_t fname_len, arch_len, entry_len;
447+
char *fname, *arch = NULL, *path, *actual;
448+
size_t fname_len, arch_len;
449449
size_t path_len, actual_len;
450450
phar_archive_data *pphar;
451451
#ifdef PHP_WIN32
@@ -476,9 +476,8 @@ PHP_METHOD(Phar, mount)
476476
}
477477
#endif
478478

479-
if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, NULL, NULL, 2, 0)) {
480-
entry = NULL;
481-
479+
zend_string *entry = NULL;
480+
if (fname_len > 7 && !memcmp(fname, "phar://", 7) && SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, NULL, 2, 0)) {
482481
if (path_len > 7 && !memcmp(path, "phar://", 7)) {
483482
zend_throw_exception_ex(phar_ce_PharException, 0, "Can only mount internal paths within a phar archive, use a relative path instead of \"%s\"", path);
484483
efree(arch);
@@ -505,8 +504,8 @@ PHP_METHOD(Phar, mount)
505504
zend_throw_exception_ex(phar_ce_PharException, 0, "Mounting of %s to %s within phar %s failed", path, actual, arch);
506505
}
507506

508-
if (entry && path == entry) {
509-
efree(entry);
507+
if (entry && path == ZSTR_VAL(entry)) {
508+
zend_string_release_ex(entry, false);
510509
}
511510

512511
if (arch) {
@@ -522,9 +521,9 @@ PHP_METHOD(Phar, mount)
522521
}
523522

524523
goto carry_on;
525-
} else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, &entry_len, 2, 0)) {
526-
path = entry;
527-
path_len = entry_len;
524+
} else if (SUCCESS == phar_split_fname(path, path_len, &arch, &arch_len, &entry, 2, 0)) {
525+
path = ZSTR_VAL(entry);
526+
path_len = ZSTR_LEN(entry);
528527
goto carry_on2;
529528
}
530529

@@ -1078,9 +1077,9 @@ static const spl_other_handler phar_spl_foreign_handler = {
10781077
*/
10791078
PHP_METHOD(Phar, __construct)
10801079
{
1081-
char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname;
1080+
char *fname, *alias = NULL, *error, *arch = NULL, *save_fname;
10821081
size_t fname_len, alias_len = 0;
1083-
size_t arch_len, entry_len;
1082+
size_t arch_len;
10841083
bool is_data;
10851084
zend_long flags = SPL_FILE_DIR_SKIPDOTS|SPL_FILE_DIR_UNIXPATHS;
10861085
zend_long format = 0;
@@ -1108,7 +1107,8 @@ PHP_METHOD(Phar, __construct)
11081107
}
11091108

11101109
save_fname = fname;
1111-
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, !is_data, 2)) {
1110+
zend_string *entry = NULL;
1111+
if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, !is_data, 2)) {
11121112
/* use arch (the basename for the archive) for fname instead of fname */
11131113
/* this allows support for RecursiveDirectoryIterator of subdirectories */
11141114
#ifdef PHP_WIN32
@@ -1133,7 +1133,7 @@ PHP_METHOD(Phar, __construct)
11331133
}
11341134

11351135
if (entry) {
1136-
efree(entry);
1136+
zend_string_release_ex(entry, false);
11371137
}
11381138

11391139
if (error) {
@@ -1166,7 +1166,7 @@ PHP_METHOD(Phar, __construct)
11661166
zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
11671167
"Phar class can only be used for executable tar and zip archives");
11681168
}
1169-
efree(entry);
1169+
zend_string_release_ex(entry, false);
11701170
RETURN_THROWS();
11711171
}
11721172

@@ -1184,9 +1184,9 @@ PHP_METHOD(Phar, __construct)
11841184
file_name_for_recursive_director_iterator_constructor = zend_string_concat3(
11851185
ZEND_STRL("phar://"),
11861186
phar_data->fname, phar_data->fname_len,
1187-
entry, entry_len
1187+
ZSTR_VAL(entry), ZSTR_LEN(entry)
11881188
);
1189-
efree(entry);
1189+
zend_string_release_ex(entry, false);
11901190
} else {
11911191
file_name_for_recursive_director_iterator_constructor = zend_string_concat2(
11921192
ZEND_STRL("phar://"),
@@ -1289,7 +1289,7 @@ PHP_METHOD(Phar, unlinkArchive)
12891289
if (
12901290
zend_file_name
12911291
&& zend_string_starts_with_literal_ci(zend_file_name, "phar://")
1292-
&& SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, NULL, NULL, 2, 0)
1292+
&& SUCCESS == phar_split_fname(ZSTR_VAL(zend_file_name), ZSTR_LEN(zend_file_name), &arch, &arch_len, NULL, 2, 0)
12931293
) {
12941294
if (arch_len == fname_len && !memcmp(arch, fname, arch_len)) {
12951295
zend_throw_exception_ex(phar_ce_PharException, 0, "phar archive \"%s\" cannot be unlinked from within itself", fname);
@@ -4392,11 +4392,10 @@ PHP_METHOD(Phar, extractTo)
43924392
/* {{{ Construct a Phar entry object */
43934393
PHP_METHOD(PharFileInfo, __construct)
43944394
{
4395-
char *fname, *arch, *entry, *error;
4395+
char *fname, *arch, *error;
43964396
size_t fname_len;
4397-
size_t arch_len, entry_len;
4397+
size_t arch_len;
43984398
phar_entry_object *entry_obj;
4399-
phar_entry_info *entry_info;
44004399
phar_archive_data *phar_data;
44014400
zval arg1;
44024401

@@ -4411,7 +4410,8 @@ PHP_METHOD(PharFileInfo, __construct)
44114410
RETURN_THROWS();
44124411
}
44134412

4414-
if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0) == FAILURE) {
4413+
zend_string *entry = NULL;
4414+
if (fname_len < 7 || memcmp(fname, "phar://", 7) || phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, 2, 0) == FAILURE) {
44154415
zend_throw_exception_ex(spl_ce_RuntimeException, 0,
44164416
"'%s' is not a valid phar archive URL (must have at least phar://filename.phar)", fname);
44174417
RETURN_THROWS();
@@ -4431,16 +4431,17 @@ PHP_METHOD(PharFileInfo, __construct)
44314431
RETURN_THROWS();
44324432
}
44334433

4434-
if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 1, &error, true)) == NULL) {
4434+
phar_entry_info *entry_info = phar_get_entry_info_dir(phar_data, ZSTR_VAL(entry), ZSTR_LEN(entry), 1, &error, true);
4435+
if (UNEXPECTED(!entry_info)) {
44354436
zend_throw_exception_ex(spl_ce_RuntimeException, 0,
4436-
"Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error ? ", " : "", error ? error : "");
4437+
"Cannot access phar file entry '%s' in archive '%s'%s%s", ZSTR_VAL(entry), arch, error ? ", " : "", error ? error : "");
4438+
zend_string_release_ex(entry, false);
44374439
efree(arch);
4438-
efree(entry);
44394440
RETURN_THROWS();
44404441
}
44414442

4443+
zend_string_release_ex(entry, false);
44424444
efree(arch);
4443-
efree(entry);
44444445

44454446
entry_obj->entry = entry_info;
44464447
if (!entry_info->is_persistent && !entry_info->is_temp_dir) {

ext/phar/stream.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ const php_stream_wrapper php_stream_phar_wrapper = {
5858
php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const char *mode, int options) /* {{{ */
5959
{
6060
php_url *resource;
61-
char *arch = NULL, *entry = NULL, *error;
62-
size_t arch_len, entry_len;
61+
char *arch = NULL, *error;
62+
size_t arch_len;
6363

6464
if (strncasecmp(filename, "phar://", 7)) {
6565
return NULL;
@@ -70,7 +70,8 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const
7070
}
7171
return NULL;
7272
}
73-
if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, &entry_len, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) {
73+
zend_string *entry = NULL;
74+
if (phar_split_fname(filename, strlen(filename), &arch, &arch_len, &entry, 2, (mode[0] == 'w' ? 2 : 0)) == FAILURE) {
7475
if (!(options & PHP_STREAM_URL_STAT_QUIET)) {
7576
if (arch && !entry) {
7677
php_stream_wrapper_log_error(wrapper, options, "phar error: no directory in \"%s\", must have at least phar://%s/ for root directory (always use full path to a new phar)", filename, arch);
@@ -85,8 +86,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const
8586
resource->scheme = ZSTR_INIT_LITERAL("phar", 0);
8687
resource->host = zend_string_init(arch, arch_len, 0);
8788
efree(arch);
88-
resource->path = zend_string_init(entry, entry_len, 0);
89-
efree(entry);
89+
resource->path = entry;
9090

9191
#ifdef MBO_0
9292
if (resource) {

ext/phar/util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data
300300
goto splitted;
301301
}
302302

303-
if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, NULL, 1, 0)) {
303+
if (!is_file_a_phar_wrapper || SUCCESS != phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), &arch, &arch_len, NULL, 1, 0)) {
304304
return NULL;
305305
}
306306

@@ -344,7 +344,7 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data
344344

345345
if (ret && zend_string_starts_with_literal_ci(ret, "phar://")) {
346346
/* found phar:// */
347-
if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, NULL, NULL, 1, 0)) {
347+
if (SUCCESS != phar_split_fname(ZSTR_VAL(ret), ZSTR_LEN(ret), &arch, &arch_len, NULL, 1, 0)) {
348348
return ret;
349349
}
350350

0 commit comments

Comments
 (0)