]> granicus.if.org Git - php/commitdiff
[DOC] add phar.cache_list, a PATH_SEPARATOR-separated list of full paths to phar...
authorGreg Beaver <cellog@php.net>
Thu, 12 Jun 2008 18:56:23 +0000 (18:56 +0000)
committerGreg Beaver <cellog@php.net>
Thu, 12 Jun 2008 18:56:23 +0000 (18:56 +0000)
at startup.  This caches the manifest, so that on first access to a phar archive, no file manifest parsing occurs.

This could use further tweaking.  For instance, the full copy of the manifest into the current process may be unnecessary if refcounting could be external
to the manifest.  This would be another significant gain.  With APC, I measure a slight perf increase to 19 req/sec up from 16 req/sec, without it approaches
regular PHP at 3.8 req/sec (regular is 4 req/sec).  This is benching phpMyAdmin

ext/phar/phar.c
ext/phar/phar.phar
ext/phar/phar_internal.h
ext/phar/tar.c
ext/phar/tests/phpinfo_001.phpt
ext/phar/tests/phpinfo_002.phpt
ext/phar/tests/phpinfo_003.phpt
ext/phar/tests/phpinfo_004.phpt
ext/phar/zip.c

index ded61ce31cc0ad94ab5dfe23d2629e83510af707..629741866e7b11af1d5983568ebec938ef03fcad 100644 (file)
@@ -43,6 +43,7 @@
 #ifndef PHAR_HAVE_OPENSSL
 static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end, char *key, int key_len, char **signature, int *signature_len TSRMLS_DC);
 #endif
+static void destroy_phar_data(void *pDest);
 
 ZEND_DECLARE_MODULE_GLOBALS(phar)
 #if PHP_VERSION_ID >= 50300
@@ -112,9 +113,94 @@ ZEND_INI_MH(phar_ini_modify_handler) /* {{{ */
 }
 /* }}}*/
 
+/* this global stores the global cached pre-parsed manifests */
+static HashTable cached_phars;
+static HashTable cached_alias;
+
+static void phar_split_cache_list(TSRMLS_D)
+{
+       char *tmp;
+       char *key, *lasts, *end;
+       char ds[1];
+       phar_archive_data *phar;
+
+       if (!PHAR_GLOBALS->cache_list || !(PHAR_GLOBALS->cache_list[0])) {
+               return;
+       }
+
+       ds[0] = DEFAULT_DIR_SEPARATOR;
+       zend_init_rsrc_list(TSRMLS_C);
+       tmp = estrdup(PHAR_GLOBALS->cache_list);
+
+       /* fake request startup */
+       PHAR_GLOBALS->request_init = 1;
+       PHAR_G(has_bz2) = zend_hash_exists(&module_registry, "bz2", sizeof("bz2"));
+       PHAR_G(has_zlib) = zend_hash_exists(&module_registry, "zlib", sizeof("zlib"));
+       zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data,  1);
+       zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 1);
+       PHAR_GLOBALS->manifest_cached = 1;
+       PHAR_GLOBALS->persist = 1;
+
+       for (key = php_strtok_r(tmp, ds, &lasts);
+                       key;
+                       key = php_strtok_r(NULL, ds, &lasts))
+       {
+               end = strchr(key, DEFAULT_DIR_SEPARATOR);
+               if (end) {
+                       if (SUCCESS == phar_open_from_filename(key, end - key, NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+finish_up:
+                               php_stream_close(phar->fp);
+                               phar->fp = NULL;
+                       } else {
+finish_error:
+                               PHAR_GLOBALS->persist = 0;
+                               PHAR_GLOBALS->manifest_cached = 0;
+                               zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC);
+                               efree(tmp);
+                               zend_hash_destroy(&(PHAR_G(phar_fname_map)));
+                               PHAR_GLOBALS->phar_fname_map.arBuckets = 0;
+                               zend_hash_destroy(&(PHAR_G(phar_alias_map)));
+                               PHAR_GLOBALS->phar_alias_map.arBuckets = 0;
+                               /* free cached manifests */
+                               PHAR_GLOBALS->request_init = 0;
+                               return;
+                       }
+               } else {
+                       if (SUCCESS == phar_open_from_filename(key, strlen(key), NULL, 0, 0, &phar, NULL TSRMLS_CC)) {
+                               goto finish_up;
+                       } else {
+                               goto finish_error;
+                       }
+               }
+       }
+       PHAR_GLOBALS->persist = 0;
+       PHAR_GLOBALS->request_init = 0;
+       cached_phars = PHAR_GLOBALS->phar_fname_map;
+       cached_alias = PHAR_GLOBALS->phar_alias_map;
+       PHAR_GLOBALS->phar_fname_map.arBuckets = 0;
+       PHAR_GLOBALS->phar_alias_map.arBuckets = 0;
+
+       zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC);
+       efree(tmp);
+}
+/* }}} */
+
+ZEND_INI_MH(phar_ini_cache_list) /* {{{ */
+{
+       PHAR_G(cache_list) = new_value;
+
+       if (stage == ZEND_INI_STAGE_STARTUP) {
+               phar_split_cache_list(TSRMLS_C);
+       }
+
+       return SUCCESS;
+}
+/* }}} */
+
 PHP_INI_BEGIN()
        STD_PHP_INI_BOOLEAN( "phar.readonly",     "1", PHP_INI_ALL, phar_ini_modify_handler, readonly,     zend_phar_globals, phar_globals)
        STD_PHP_INI_BOOLEAN( "phar.require_hash", "1", PHP_INI_ALL, phar_ini_modify_handler, require_hash, zend_phar_globals, phar_globals)
+       STD_PHP_INI_ENTRY("phar.cache_list", "",  PHP_INI_SYSTEM, phar_ini_cache_list,   cache_list, zend_phar_globals, phar_globals)
 PHP_INI_END()
 
 /**
@@ -124,15 +210,15 @@ PHP_INI_END()
 void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
 {
        if (phar->alias && phar->alias != phar->fname) {
-               efree(phar->alias);
+               pefree(phar->alias, phar->is_persistent);
                phar->alias = NULL;
        }
        if (phar->fname) {
-               efree(phar->fname);
+               pefree(phar->fname, phar->is_persistent);
                phar->fname = NULL;
        }
        if (phar->signature) {
-               efree(phar->signature);
+               pefree(phar->signature, phar->is_persistent);
                phar->signature = NULL;
        }
        if (phar->manifest.arBuckets) {
@@ -144,7 +230,17 @@ void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
                phar->mounted_dirs.arBuckets = NULL;
        }
        if (phar->metadata) {
-               zval_ptr_dtor(&phar->metadata);
+               if (phar->is_persistent) {
+                       if (phar->metadata_len) {
+                               /* for zip comments that are strings */
+                               free(phar->metadata);
+                       } else {
+                               zval_internal_ptr_dtor(&phar->metadata);
+                       }
+               } else {
+                       zval_ptr_dtor(&phar->metadata);
+               }
+               phar->metadata_len = 0;
                phar->metadata = 0;
        }
        if (phar->fp) {
@@ -155,7 +251,7 @@ void phar_destroy_phar_data(phar_archive_data *phar TSRMLS_DC) /* {{{ */
                php_stream_close(phar->ufp);
                phar->fp = 0;
        }
-       efree(phar);
+       pefree(phar, phar->is_persistent);
 }
 /* }}}*/
 
@@ -272,20 +368,30 @@ void destroy_phar_manifest_entry(void *pDest) /* {{{ */
                entry->fp = 0;
        }
        if (entry->metadata) {
-               zval_ptr_dtor(&entry->metadata);
+               if (entry->is_persistent) {
+                       if (entry->metadata_len) {
+                               /* for zip comments that are strings */
+                               free(entry->metadata);
+                       } else {
+                               zval_internal_ptr_dtor(&entry->metadata);
+                       }
+               } else {
+                       zval_ptr_dtor(&entry->metadata);
+               }
+               entry->metadata_len = 0;
                entry->metadata = 0;
        }
        if (entry->metadata_str.c) {
                smart_str_free(&entry->metadata_str);
                entry->metadata_str.c = 0;
        }
-       efree(entry->filename);
+       pefree(entry->filename, entry->is_persistent);
        if (entry->link) {
-               efree(entry->link);
+               pefree(entry->link, entry->is_persistent);
                entry->link = 0;
        }
        if (entry->tmp) {
-               efree(entry->tmp);
+               pefree(entry->tmp, entry->is_persistent);
                entry->tmp = 0;
        }
 }
@@ -349,7 +455,7 @@ void phar_entry_remove(phar_entry_data *idata, char **error TSRMLS_DC) /* {{{ */
                phar_destroy_phar_data(mydata TSRMLS_CC);\
        }\
        if (signature) {\
-               efree(signature);\
+               pefree(signature, mydata->is_persistent);\
        }\
        MAPPHAR_ALLOC_FAIL(msg)
 
@@ -465,9 +571,10 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
        } else {
                buf_len = zip_metadata_len;
        }
-       
+
        if (buf_len) {
-               ALLOC_INIT_ZVAL(*metadata);
+               ALLOC_ZVAL(*metadata);
+               INIT_ZVAL(**metadata);
                p = (const unsigned char*) *buffer;
                PHP_VAR_UNSERIALIZE_INIT(var_hash);
                if (!php_var_unserialize(metadata, &p, p + buf_len,  &var_hash TSRMLS_CC)) {
@@ -477,6 +584,16 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
                        return FAILURE;
                }
                PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+               if (PHAR_G(persist)) {
+                       /* lazy init metadata */
+                       zval_ptr_dtor(metadata);
+                       *metadata = (zval *) pemalloc(buf_len, 1);
+                       memcpy(*metadata, *buffer, buf_len);
+                       if (!zip_metadata_len) {
+                               *buffer += buf_len;
+                       }
+                       return SUCCESS;
+               }
        } else {
                *metadata = NULL;
        }
@@ -494,7 +611,7 @@ static int phar_hex_str(const char *digest, size_t digest_len, char ** signature
        int pos = -1;
        size_t len = 0;
 
-       *signature = (char*)safe_emalloc(digest_len, 2, 1);
+       *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
 
        for (; len < digest_len; ++len) {
                (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
@@ -513,7 +630,7 @@ static int phar_hex_str(const char *digest, size_t digest_len, char ** signature
  * This is used by phar_open_from_filename to process the manifest, but can be called
  * directly.
  */
-int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
+static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error TSRMLS_DC) /* {{{ */
 {
        char b32[4], *buffer, *endbuffer, *savebuf;
        phar_archive_data *mydata = NULL;
@@ -988,22 +1105,33 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
                MAPPHAR_FAIL("internal corruption of phar \"%s\" (too many manifest entries for size of manifest)")
        }
 
-       mydata = ecalloc(sizeof(phar_archive_data), 1);
+       mydata = pecalloc(sizeof(phar_archive_data), 1, PHAR_G(persist));
+       mydata->is_persistent = PHAR_G(persist);
 
        /* check whether we have meta data, zero check works regardless of byte order */
-       if (phar_parse_metadata(&buffer, &mydata->metadata, 0 TSRMLS_CC) == FAILURE) {
-               MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
+       if (mydata->is_persistent) {
+               char *mysave = buffer;
+               PHAR_GET_32(buffer, mydata->metadata_len);
+               buffer = mysave;
+               if (phar_parse_metadata(&buffer, &mydata->metadata, mydata->metadata_len TSRMLS_CC) == FAILURE) {
+                       MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
+               }
+       } else {
+               if (phar_parse_metadata(&buffer, &mydata->metadata, 0 TSRMLS_CC) == FAILURE) {
+                       MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
+               }
        }
 
        /* set up our manifest */
        zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
-               zend_get_hash_value, destroy_phar_manifest_entry, 0);
+               zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent);
        zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
-               zend_get_hash_value, NULL, 0);
+               zend_get_hash_value, NULL, mydata->is_persistent);
        offset = halt_offset + manifest_len + 4;
        memset(&entry, 0, sizeof(phar_entry_info));
        entry.phar = mydata;
        entry.fp_type = PHAR_FP;
+       entry.is_persistent = mydata->is_persistent;
 
        for (manifest_index = 0; manifest_index < manifest_count; ++manifest_index) {
                if (buffer + 4 > endbuffer) {
@@ -1021,7 +1149,7 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
                } else {
                        entry.is_dir = 0;
                }
-               entry.filename = estrndup(buffer, entry.filename_len);
+               entry.filename = pestrndup(buffer, entry.filename_len, entry.is_persistent);
                buffer += entry.filename_len;
                PHAR_GET_32(buffer, entry.uncompressed_filesize);
                PHAR_GET_32(buffer, entry.timestamp);
@@ -1042,9 +1170,17 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
                        entry.filename_len--;
                        entry.flags |= PHAR_ENT_PERM_DEF_DIR;
                }
-               if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
-                       efree(entry.filename);
-                       MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+               if (entry.is_persistent) {
+                       PHAR_GET_32(buffer, entry.metadata_len);
+                       if (phar_parse_metadata(&buffer, &entry.metadata, entry.metadata_len TSRMLS_CC) == FAILURE) {
+                               pefree(entry.filename, entry.is_persistent);
+                               MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+                       }
+               } else {
+                       if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) {
+                               pefree(entry.filename, entry.is_persistent);
+                               MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\"");
+                       }
                }
                entry.offset = entry.offset_abs = offset;
                offset += entry.compressed_filesize;
@@ -1052,27 +1188,39 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
                case PHAR_ENT_COMPRESSED_GZ:
                        if (!PHAR_G(has_zlib)) {
                                if (entry.metadata) {
-                                       zval_ptr_dtor(&entry.metadata);
+                                       if (entry.is_persistent) {
+                                               free(entry.metadata);
+                                       } else {
+                                               zval_ptr_dtor(&entry.metadata);
+                                       }
                                }
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                MAPPHAR_FAIL("zlib extension is required for gz compressed .phar file \"%s\"");
                        }
                        break;
                case PHAR_ENT_COMPRESSED_BZ2:
                        if (!PHAR_G(has_bz2)) {
                                if (entry.metadata) {
-                                       zval_ptr_dtor(&entry.metadata);
+                                       if (entry.is_persistent) {
+                                               free(entry.metadata);
+                                       } else {
+                                               zval_ptr_dtor(&entry.metadata);
+                                       }
                                }
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                MAPPHAR_FAIL("bz2 extension is required for bzip2 compressed .phar file \"%s\"");
                        }
                        break;
                default:
                        if (entry.uncompressed_filesize != entry.compressed_filesize) {
                                if (entry.metadata) {
-                                       zval_ptr_dtor(&entry.metadata);
+                                       if (entry.is_persistent) {
+                                               free(entry.metadata);
+                                       } else {
+                                               zval_ptr_dtor(&entry.metadata);
+                                       }
                                }
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                MAPPHAR_FAIL("internal corruption of phar \"%s\" (compressed and uncompressed size does not match for uncompressed entry)");
                        }
                        break;
@@ -1088,7 +1236,7 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
        mydata->halt_offset = halt_offset;
        mydata->flags = manifest_flags;
        mydata->fp = fp;
-       mydata->fname = estrndup(fname, fname_len);
+       mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
 #ifdef PHP_WIN32
        phar_unixify_path_separators(mydata->fname, fname_len);
 #endif
@@ -1103,7 +1251,9 @@ int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias,
                        mydata->ext_len = (mydata->fname + mydata->fname_len) - mydata->ext;
                }
        }
-       mydata->alias = alias ? estrndup(alias, alias_len) : estrndup(mydata->fname, fname_len);
+       mydata->alias = alias ?
+               pestrndup(alias, alias_len, mydata->is_persistent) :
+               pestrndup(mydata->fname, fname_len, mydata->is_persistent);
        mydata->alias_len = alias ? alias_len : fname_len;
        mydata->sig_flags = sig_flags;
        mydata->sig_len = sig_len;
@@ -3351,6 +3501,108 @@ PHP_MSHUTDOWN_FUNCTION(phar) /* {{{ */
                zend_stream_open_function = phar_orig_zend_open;
        }
 #endif
+       if (PHAR_G(manifest_cached)) {
+               zend_hash_destroy(&(cached_phars));
+               zend_hash_destroy(&(cached_alias));
+       }
+}
+/* }}} */
+
+static void phar_update_cached_entry(void *data, void *argument) /* {{{ */
+{
+       phar_entry_info *entry = (phar_entry_info *)data;
+       TSRMLS_FETCH();
+
+       entry->phar = (phar_archive_data *)argument;
+       if (entry->link) {
+               entry->link = estrdup(entry->link);
+       }
+       if (entry->tmp) {
+               entry->tmp = estrdup(entry->tmp);
+       }
+       entry->metadata_str.c = 0;
+       entry->filename = estrndup(entry->filename, entry->filename_len);
+       if (entry->metadata) {
+               if (entry->metadata_len) {
+                       /* assume success, we would have failed before */
+                       phar_parse_metadata((char **) &entry->metadata, &entry->metadata, entry->metadata_len TSRMLS_CC);
+               } else {
+                       zval *t;
+
+                       t = entry->metadata;
+                       ALLOC_ZVAL(entry->metadata);
+                       *entry->metadata = *t;
+                       zval_copy_ctor(entry->metadata);
+#if PHP_VERSION_ID < 50300
+                       entry->metadata->refcount = 1;
+#else
+                       Z_SET_REFCOUNT_P(entry->metadata, 1);
+#endif
+
+                       entry->metadata_str.c = NULL;
+                       entry->metadata_str.len = 0;
+               }
+       }
+}
+
+static void phar_copy_cached_phar(void *data) /* {{{ */
+{
+       phar_archive_data *phar, **pphar = (phar_archive_data **)data;
+       HashTable newmanifest;
+       char *fname;
+       TSRMLS_FETCH();
+
+       phar = (phar_archive_data *) emalloc(sizeof(phar_archive_data));
+       *phar = **pphar;
+       phar->is_persistent = 0;
+       fname = phar->fname;
+       phar->fname = estrndup(phar->fname, phar->fname_len);
+       phar->ext = phar->fname + (phar->ext - fname);
+       if (phar->alias) {
+               phar->alias = estrndup(phar->alias, phar->alias_len);
+       }
+       if (phar->signature) {
+               phar->signature = estrdup(phar->signature);
+       }
+       if (phar->metadata) {
+               /* assume success, we would have failed before */
+               if (phar->metadata_len) {
+                       phar_parse_metadata((char **) &phar->metadata, &phar->metadata, phar->metadata_len TSRMLS_CC);
+               } else {
+                       zval *t;
+
+                       t = phar->metadata;
+                       ALLOC_ZVAL(phar->metadata);
+                       *phar->metadata = *t;
+                       zval_copy_ctor(phar->metadata);
+#if PHP_VERSION_ID < 50300
+                       phar->metadata->refcount = 1;
+#else
+                       Z_SET_REFCOUNT_P(phar->metadata, 1);
+#endif
+               }
+       }
+       zend_hash_init(&newmanifest, sizeof(phar_entry_info),
+               zend_get_hash_value, destroy_phar_manifest_entry, 0);
+       zend_hash_copy(&newmanifest, &(*pphar)->manifest, NULL, NULL, sizeof(phar_entry_info));
+       zend_hash_apply_with_argument(&newmanifest, (apply_func_arg_t) phar_update_cached_entry, (void *)phar TSRMLS_CC);
+       phar->manifest = newmanifest;
+       zend_hash_init(&phar->mounted_dirs, sizeof(char *),
+               zend_get_hash_value, NULL, 0);
+       *pphar = phar;
+}
+/* }}} */
+
+static int phar_update_alias_map(void *data) /* {{{ */
+{
+       phar_archive_data **pphar, **old = (phar_archive_data **)data;
+       TSRMLS_FETCH();
+
+       zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), (*old)->fname, (*old)->fname_len, (void **) &pphar);
+       if (pphar) {
+               *old = *pphar;
+       }
+       return ZEND_HASH_APPLY_KEEP;
 }
 /* }}} */
 
@@ -3365,11 +3617,18 @@ void phar_request_initialize(TSRMLS_D) /* {{{ */
                PHAR_GLOBALS->request_done = 0;
                zend_hash_init(&(PHAR_GLOBALS->phar_fname_map), sizeof(phar_archive_data*), zend_get_hash_value, destroy_phar_data,  0);
                zend_hash_init(&(PHAR_GLOBALS->phar_alias_map), sizeof(phar_archive_data*), zend_get_hash_value, NULL, 0);
+               if (PHAR_G(manifest_cached)) {
+                       zend_hash_copy(&(PHAR_GLOBALS->phar_fname_map), &cached_phars, phar_copy_cached_phar, NULL, sizeof(phar_archive_data *));
+                       zend_hash_copy(&(PHAR_GLOBALS->phar_alias_map), &cached_alias, NULL, NULL, sizeof(phar_archive_data *));
+                       zend_hash_apply(&(PHAR_GLOBALS->phar_alias_map), (apply_func_t) phar_update_alias_map TSRMLS_CC);
+               }
                zend_hash_init(&(PHAR_GLOBALS->phar_SERVER_mung_list), sizeof(const char *),       zend_get_hash_value, NULL, 0);
                PHAR_G(cwd) = NULL;
                PHAR_G(cwd_len) = 0;
                PHAR_G(cwd_init) = 0;
-               phar_intercept_functions(TSRMLS_C);
+               if (!PHAR_G(orig_fopen)) {
+                       phar_intercept_functions(TSRMLS_C);
+               }
        }
 }
 /* }}} */
@@ -3439,6 +3698,8 @@ PHP_MINFO_FUNCTION(phar) /* {{{ */
 static zend_module_dep phar_deps[] = {
        ZEND_MOD_OPTIONAL("apc")
        ZEND_MOD_OPTIONAL("openssl")
+       ZEND_MOD_OPTIONAL("zlib")
+       ZEND_MOD_OPTIONAL("bz2")
 #if HAVE_SPL
        ZEND_MOD_REQUIRED("spl")
 #endif
index 20fea1786c44129b325d2042afdceab0c8542205..c68028875c164b4ceea9962a0eac7e134de3c62b 100755 (executable)
Binary files a/ext/phar/phar.phar and b/ext/phar/phar.phar differ
index 4d8ba8475b2ef5ebfa34517a52e372f09fd0a9af..411411fb9de152a807496b383ad29842b069ef90 100755 (executable)
@@ -137,6 +137,9 @@ ZEND_BEGIN_MODULE_GLOBALS(phar)
        HashTable   phar_alias_map;
        HashTable   phar_SERVER_mung_list;
        int         readonly;
+       char*       cache_list;
+       int         manifest_cached;
+       int         persist;
        int         has_zlib;
        int         has_bz2;
        zend_bool   readonly_orig;
@@ -228,6 +231,7 @@ typedef struct _phar_entry_info {
        /* when changing compression, save old flags in case fp is NULL */
        php_uint32               old_flags;
        zval                     *metadata;
+       int                      metadata_len; /* only used for cached manifests */
        php_uint32               filename_len;
        char                     *filename;
        enum phar_fp_type        fp_type;
@@ -258,6 +262,8 @@ typedef struct _phar_entry_info {
        char                     tar_type;
        /* zip-based phar file stuff */
        int                      is_zip:1;
+       /* for cached phar entries */
+       int                      is_persistent:1;
 } phar_entry_info;
 
 /* information about a phar file (the archive itself) */
@@ -286,6 +292,7 @@ struct _phar_archive_data {
        int                      sig_len;
        char                     *signature;
        zval                     *metadata;
+       int                      metadata_len; /* only used for cached manifests */
        /* if 1, then this alias was manually specified by the user and is not a permanent alias */
        int                      is_temporary_alias:1;
        int                      is_modified:1;
@@ -299,6 +306,8 @@ struct _phar_archive_data {
        int                      is_tar:1;
        /* PharData variables       */
        int                      is_data:1;
+       /* for cached phar manifests */
+       int                      is_persistent:1;
 };
 
 #define PHAR_MIME_PHP '\0'
index b3d69cc88f8cdcc50474dad53778810d337e3817..1cd5046aa0930da0f5b78bbd7c6694adff330d00 100644 (file)
@@ -214,11 +214,12 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
        hdr = (tar_header*)buf;
        old = (memcmp(hdr->magic, "ustar", sizeof("ustar")-1) != 0);
 
-       myphar = (phar_archive_data *) ecalloc(1, sizeof(phar_archive_data));
+       myphar = (phar_archive_data *) pecalloc(1, sizeof(phar_archive_data), PHAR_G(persist));
+       myphar->is_persistent = PHAR_G(persist);
        zend_hash_init(&myphar->manifest, sizeof(phar_entry_info),
-               zend_get_hash_value, destroy_phar_manifest_entry, 0);
+               zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent);
        zend_hash_init(&myphar->mounted_dirs, sizeof(char *),
-               zend_get_hash_value, NULL, 0);
+               zend_get_hash_value, NULL, myphar->is_persistent);
        myphar->is_tar = 1;
        /* remember whether this entire phar was compressed with gz/bzip2 */
        myphar->flags = compression;
@@ -257,9 +258,9 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                /* some tar programs store directories with trailing slash */
                                entry.filename_len--;
                        }
-                       entry.filename = estrndup(name, entry.filename_len);
+                       entry.filename = pestrndup(name, entry.filename_len, myphar->is_persistent);
                } else {
-                       entry.filename = estrdup(hdr->name);
+                       entry.filename = pestrdup(hdr->name, myphar->is_persistent);
                        entry.filename_len = strlen(entry.filename);
                        if (entry.filename[entry.filename_len - 1] == '/') {
                                /* some tar programs store directories with trailing slash */
@@ -271,13 +272,13 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                        if (error) {
                                spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (checksum mismatch of file \"%s\")", fname, entry.filename);
                        }
-                       efree(entry.filename);
+                       pefree(entry.filename, myphar->is_persistent);
                        php_stream_close(fp);
                        zend_hash_destroy(&myphar->manifest);
                        myphar->manifest.arBuckets = 0;
                        zend_hash_destroy(&myphar->mounted_dirs);
                        myphar->mounted_dirs.arBuckets = 0;
-                       efree(myphar);
+                       pefree(myphar, myphar->is_persistent);
                        return FAILURE;
                }
 
@@ -286,6 +287,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                entry.fp_type = PHAR_FP;
                entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
                entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
+               entry.is_persistent = myphar->is_persistent;
 
 #ifndef S_ISDIR
 #define S_ISDIR(mode)  (((mode)&S_IFMT) == S_IFDIR)
@@ -305,13 +307,13 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                if (error) {
                                        spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname);
                                }
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                php_stream_close(fp);
                                zend_hash_destroy(&myphar->manifest);
                                myphar->manifest.arBuckets = 0;
                                zend_hash_destroy(&myphar->mounted_dirs);
                                myphar->mounted_dirs.arBuckets = 0;
-                               efree(myphar);
+                               pefree(myphar, entry.is_persistent);
                                return FAILURE;
                        }
                        entry.link = estrdup(hdr->linkname);
@@ -329,7 +331,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                myphar->manifest.arBuckets = 0;
                                zend_hash_destroy(&myphar->mounted_dirs);
                                myphar->mounted_dirs.arBuckets = 0;
-                               efree(myphar);
+                               pefree(myphar, myphar->is_persistent);
                                return FAILURE;
                        }
                }
@@ -345,7 +347,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                myphar->manifest.arBuckets = 0;
                                zend_hash_destroy(&myphar->mounted_dirs);
                                myphar->mounted_dirs.arBuckets = 0;
-                               efree(myphar);
+                               pefree(myphar, myphar->is_persistent);
                                return FAILURE;
                        }
                        read = php_stream_read(fp, buf, size);
@@ -366,10 +368,10 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                        myphar->manifest.arBuckets = 0;
                                        zend_hash_destroy(&myphar->mounted_dirs);
                                        myphar->mounted_dirs.arBuckets = 0;
-                                       efree(myphar);
+                                       pefree(myphar, myphar->is_persistent);
                                        return FAILURE;
                                }
-                               actual_alias = estrndup(buf, size);
+                               actual_alias = pestrndup(buf, size, myphar->is_persistent);
                                myphar->alias = actual_alias;
                                myphar->alias_len = size;
                                php_stream_seek(fp, pos, SEEK_SET);
@@ -382,7 +384,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                myphar->manifest.arBuckets = 0;
                                zend_hash_destroy(&myphar->mounted_dirs);
                                myphar->mounted_dirs.arBuckets = 0;
-                               efree(myphar);
+                               pefree(myphar, myphar->is_persistent);
                                return FAILURE;
                        }
                }
@@ -399,7 +401,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                myphar->manifest.arBuckets = 0;
                                zend_hash_destroy(&myphar->mounted_dirs);
                                myphar->mounted_dirs.arBuckets = 0;
-                               efree(myphar);
+                               pefree(myphar, myphar->is_persistent);
                                return FAILURE;
                        }
                }
@@ -413,11 +415,11 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                        myphar->manifest.arBuckets = 0;
                        zend_hash_destroy(&myphar->mounted_dirs);
                        myphar->mounted_dirs.arBuckets = 0;
-                       efree(myphar);
+                       pefree(myphar, myphar->is_persistent);
                        return FAILURE;
                }
        } while (read != 0);
-       myphar->fname = estrndup(fname, fname_len);
+       myphar->fname = pestrndup(fname, fname_len, myphar->is_persistent);
 #ifdef PHP_WIN32
        phar_unixify_path_separators(myphar->fname, fname_len);
 #endif
@@ -449,7 +451,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                myphar->manifest.arBuckets = 0;
                zend_hash_destroy(&myphar->mounted_dirs);
                myphar->mounted_dirs.arBuckets = 0;
-               efree(myphar);
+               pefree(myphar, myphar->is_persistent);
                return FAILURE;
        }
        myphar = *actual;
@@ -481,10 +483,10 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias,
                                }
                        }
                        zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, myphar->alias_len, (void*)&myphar, sizeof(phar_archive_data*), NULL);
-                       myphar->alias = estrndup(alias, alias_len);
+                       myphar->alias = pestrndup(alias, alias_len, myphar->is_persistent);
                        myphar->alias_len = alias_len;
                } else {
-                       myphar->alias = estrndup(myphar->fname, fname_len);
+                       myphar->alias = pestrndup(myphar->fname, fname_len, myphar->is_persistent);
                        myphar->alias_len = fname_len;
                }
                myphar->is_temporary_alias = 1;
index 7b31185827a73442baf8d8fe87cbb392917943f0..400a553226d642e676e5b4585fa924cb2dab6861 100644 (file)
@@ -7,6 +7,7 @@ Phar: phpinfo display 1
 --INI--
 phar.readonly=0
 phar.require_hash=0
+phar.cache_list=
 --FILE--
 <?php
 phpinfo(INFO_MODULES);
@@ -33,6 +34,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
 Phar fully realized by Gregory Beaver and Marcus Boerger.
 Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
 Directive => Local Value => Master Value
+phar.cache_list => no value => no value
 phar.readonly => Off => Off
 phar.require_hash => Off => Off
 %a
@@ -53,6 +55,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
 Phar fully realized by Gregory Beaver and Marcus Boerger.
 Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
 Directive => Local Value => Master Value
+phar.cache_list => no value => no value
 phar.readonly => On => Off
 phar.require_hash => On => Off
 %a
index 1e0e567affe841344f900bd60d90c6c983793eeb..5fd0370d3397081f533a5018ed103683d9ebb354 100644 (file)
@@ -7,6 +7,7 @@ Phar: phpinfo display 2
 --INI--
 phar.readonly=1
 phar.require_hash=1
+phar.cache_list=
 --FILE--
 <?php
 phpinfo(INFO_MODULES);
@@ -31,6 +32,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
 Phar fully realized by Gregory Beaver and Marcus Boerger.
 Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
 Directive => Local Value => Master Value
+phar.cache_list => no value => no value
 phar.readonly => On => On
 phar.require_hash => On => On
 %a
index 23bc0a773a5e0196637cdedfc5a35c2609716ca2..16690b476cf28a0b473b080b14f3c33f4a592deb 100644 (file)
@@ -7,6 +7,7 @@ Phar: phpinfo display 3
 --INI--
 phar.readonly=1
 phar.require_hash=1
+phar.cache_list=
 --FILE--
 <?php
 phpinfo(INFO_MODULES);
@@ -31,6 +32,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.
 Phar fully realized by Gregory Beaver and Marcus Boerger.
 Portions of tar implementation Copyright (c) 2003-2007 Tim Kientzle.
 Directive => Local Value => Master Value
+phar.cache_list => no value => no value
 phar.readonly => On => On
 phar.require_hash => On => On
 %a
index 1dbccda8899d4fe7f66429b4a3d6ecf39bf029a1..b541c6f00a2e51103d60c8c649b40750ebb7bfb2 100644 (file)
@@ -7,6 +7,7 @@ Phar: phpinfo display 4
 --INI--
 phar.readonly=0
 phar.require_hash=0
+phar.cache_list=
 --POST--
 a=b
 --FILE--
@@ -37,6 +38,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full
 </table><br />
 <table border="0" cellpadding="3" width="600">
 <tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
+<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
 <tr><td class="e">phar.readonly</td><td class="v">Off</td><td class="v">Off</td></tr>
 <tr><td class="e">phar.require_hash</td><td class="v">Off</td><td class="v">Off</td></tr>
 </table><br />
@@ -59,6 +61,7 @@ Phar based on pear/PHP_Archive, original concept by Davey Shafik.<br />Phar full
 </table><br />
 <table border="0" cellpadding="3" width="600">
 <tr class="h"><th>Directive</th><th>Local Value</th><th>Master Value</th></tr>
+<tr><td class="e">phar.cache_list</td><td class="v"><i>no value</i></td><td class="v"><i>no value</i></td></tr>
 <tr><td class="e">phar.readonly</td><td class="v">On</td><td class="v">Off</td></tr>
 <tr><td class="e">phar.require_hash</td><td class="v">On</td><td class="v">Off</td></tr>
 </table><br />
index 046c2fd6ebc7358d52a1e68f31050f5928fbfcf2..dbeddfb2f925f0862c787ffa03626cf09e1e8762 100644 (file)
@@ -193,7 +193,8 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
                                php_stream_close(fp);
                                return FAILURE;
                        }
-                       mydata = ecalloc(sizeof(phar_archive_data), 1);
+                       mydata = pecalloc(sizeof(phar_archive_data), 1, PHAR_G(persist));
+                       mydata->is_persistent = PHAR_G(persist);
 
                        /* read in archive comment, if any */
                        if (locator.comment_len) {
@@ -205,13 +206,21 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
                                                spprintf(error, 4096, "phar error: corrupt zip archive, zip file comment truncated in zip-based phar \"%s\"", fname);
                                        }
                                        php_stream_close(fp);
-                                       efree(mydata);
+                                       pefree(mydata, mydata->is_persistent);
                                        return FAILURE;
                                }
+                               mydata->metadata_len = PHAR_GET_16(locator.comment_len);
                                if (phar_parse_metadata(&metadata, &mydata->metadata, PHAR_GET_16(locator.comment_len) TSRMLS_CC) == FAILURE) {
+                                       mydata->metadata_len = 0;
                                        /* if not valid serialized data, it is a regular string */
-                                       ALLOC_INIT_ZVAL(mydata->metadata);
-                                       ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 1);
+                                       if (entry.is_persistent) {
+                                               ALLOC_PERMANENT_ZVAL(mydata->metadata);
+                                       } else {
+                                               ALLOC_ZVAL(mydata->metadata);
+                                       }
+                                       INIT_ZVAL(*mydata->metadata);
+                                       metadata = pestrndup(metadata, PHAR_GET_16(locator.comment_len), mydata->is_persistent);
+                                       ZVAL_STRINGL(mydata->metadata, metadata, PHAR_GET_16(locator.comment_len), 0);
                                }
                        } else {
                                mydata->metadata = NULL;
@@ -225,7 +234,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias,
        }
        return FAILURE;
 foundit:
-       mydata->fname = estrndup(fname, fname_len);
+       mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent);
 #ifdef PHP_WIN32
        phar_unixify_path_separators(mydata->fname, fname_len);
 #endif
@@ -246,12 +255,13 @@ foundit:
        php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET);
        /* read in central directory */
        zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
-               zend_get_hash_value, destroy_phar_manifest_entry, 0);
+               zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent);
        zend_hash_init(&mydata->mounted_dirs, sizeof(char *),
-               zend_get_hash_value, NULL, 0);
+               zend_get_hash_value, NULL, mydata->is_persistent);
        entry.phar = mydata;
        entry.is_zip = 1;
        entry.fp_type = PHAR_FP;
+       entry.is_persistent = mydata->is_persistent;
 #define PHAR_ZIP_FAIL(errmsg) \
                        zend_hash_destroy(&mydata->manifest); \
                        mydata->manifest.arBuckets = 0; \
@@ -264,11 +274,11 @@ foundit:
                        if (error) { \
                                spprintf(error, 4096, "phar error: %s in zip-based phar \"%s\"", errmsg, mydata->fname); \
                        } \
-                       efree(mydata->fname); \
+                       pefree(mydata->fname, mydata->is_persistent); \
                        if (mydata->alias) { \
-                               efree(mydata->alias); \
+                               pefree(mydata->alias, mydata->is_persistent); \
                        } \
-                       efree(mydata); \
+                       pefree(mydata, mydata->is_persistent); \
                        return FAILURE;
 
        /* add each central directory item to the manifest */
@@ -299,9 +309,9 @@ foundit:
                        PHAR_ZIP_FAIL("Cannot process zips created from stdin (zero-length filename)");
                }
                entry.filename_len = PHAR_GET_16(zipentry.filename_len);
-               entry.filename = (char *) emalloc(entry.filename_len + 1);
+               entry.filename = (char *) pemalloc(entry.filename_len + 1, entry.is_persistent);
                if (entry.filename_len != php_stream_read(fp, entry.filename, entry.filename_len)) {
-                       efree(entry.filename);
+                       pefree(entry.filename, entry.is_persistent);
                        PHAR_ZIP_FAIL("unable to read in filename from central directory, truncated");
                }
                entry.filename[entry.filename_len] = '\0';
@@ -339,56 +349,63 @@ foundit:
                                }
                                break;
                        case 1 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (Shrunk) used in this zip");
                        case 2 :
                        case 3 :
                        case 4 :
                        case 5 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (Reduce) used in this zip");
                        case 6 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (Implode) used in this zip");
                        case 7 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (Tokenize) used in this zip");
                        case 9 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (Deflate64) used in this zip");
                        case 10 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (PKWare Implode/old IBM TERSE) used in this zip");
                        case 14 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (LZMA) used in this zip");
                        case 18 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (IBM TERSE) used in this zip");
                        case 19 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (IBM LZ77) used in this zip");
                        case 97 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (WavPack) used in this zip");
                        case 98 :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (PPMd) used in this zip");
                        default :
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unsupported compression method (unknown) used in this zip");
                }
                /* get file metadata */
                if (zipentry.comment_len) {
                        if (PHAR_GET_16(zipentry.comment_len) != php_stream_read(fp, buf, PHAR_GET_16(zipentry.comment_len))) {
-                               efree(entry.filename);
+                               pefree(entry.filename, entry.is_persistent);
                                PHAR_ZIP_FAIL("unable to read in file comment, truncated");
                        }
                        p = buf;
+                       entry.metadata_len = zipentry.comment_len;
                        if (phar_parse_metadata(&p, &(entry.metadata), PHAR_GET_16(zipentry.comment_len) TSRMLS_CC) == FAILURE) {
+                               entry.metadata_len = 0;
                                /* if not valid serialized data, it is a regular string */
-                               ALLOC_INIT_ZVAL(entry.metadata);
-                               ZVAL_STRINGL(entry.metadata, buf, PHAR_GET_16(zipentry.comment_len), 1);
+                               if (entry.is_persistent) {
+                                       ALLOC_PERMANENT_ZVAL(entry.metadata);
+                               } else {
+                                       ALLOC_ZVAL(entry.metadata);
+                               }
+                               INIT_ZVAL(*entry.metadata);
+                               ZVAL_STRINGL(entry.metadata, pestrndup(buf, PHAR_GET_16(zipentry.comment_len), entry.is_persistent), PHAR_GET_16(zipentry.comment_len), 0);
                        }
                } else {
                        entry.metadata = NULL;
@@ -405,12 +422,12 @@ foundit:
                        if (entry.flags & PHAR_ENT_COMPRESSED_GZ) {
                                filter = php_stream_filter_create("zlib.inflate", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
                                if (!filter) {
-                                       efree(entry.filename);
+                                       pefree(entry.filename, entry.is_persistent);
                                        PHAR_ZIP_FAIL("unable to decompress alias, zlib filter creation failed");
                                }
                                php_stream_filter_append(&fp->readfilters, filter);
                                if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
-                                       efree(entry.filename);
+                                       pefree(entry.filename, entry.is_persistent);
                                        PHAR_ZIP_FAIL("unable to read in alias, truncated");
                                }
                                php_stream_filter_flush(filter, 1);
@@ -419,20 +436,20 @@ foundit:
                                php_stream_filter *filter;
                                filter = php_stream_filter_create("bzip2.decompress", NULL, php_stream_is_persistent(fp) TSRMLS_CC);
                                if (!filter) {
-                                       efree(entry.filename);
+                                       pefree(entry.filename, entry.is_persistent);
                                        PHAR_ZIP_FAIL("unable to read in alias, bzip2 filter creation failed");
                                }
                                php_stream_filter_append(&fp->readfilters, filter);
                                php_stream_filter_append(&fp->readfilters, filter);
                                if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
-                                       efree(entry.filename);
+                                       pefree(entry.filename, entry.is_persistent);
                                        PHAR_ZIP_FAIL("unable to read in alias, truncated");
                                }
                                php_stream_filter_flush(filter, 1);
                                php_stream_filter_remove(filter, 1 TSRMLS_CC);
                        } else {
                                if (!(entry.uncompressed_filesize = php_stream_copy_to_mem(fp, &actual_alias, entry.uncompressed_filesize, 0)) || !actual_alias) {
-                                       efree(entry.filename);
+                                       pefree(entry.filename, entry.is_persistent);
                                        PHAR_ZIP_FAIL("unable to read in alias, truncated");
                                }
                        }
@@ -471,7 +488,10 @@ foundit:
                                return FAILURE;
                        }
                }
-               mydata->alias = actual_alias;
+               mydata->alias = entry.is_persistent ? pestrndup(actual_alias, mydata->alias_len, 1) : actual_alias;
+               if (entry.is_persistent) {
+                       efree(actual_alias);
+               }
                zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
        } else {
                phar_archive_data **fd_ptr;
@@ -487,10 +507,10 @@ foundit:
                                }
                        }
                        zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), actual_alias, mydata->alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
-                       mydata->alias = estrndup(alias, alias_len);
+                       mydata->alias = pestrndup(alias, alias_len, mydata->is_persistent);
                        mydata->alias_len = alias_len;
                } else {
-                       mydata->alias = estrndup(mydata->fname, fname_len);
+                       mydata->alias = pestrndup(mydata->fname, fname_len, mydata->is_persistent);
                        mydata->alias_len = fname_len;
                }
                mydata->is_temporary_alias = 1;