]> granicus.if.org Git - php/commitdiff
fix memleak in unlink()
authorGreg Beaver <cellog@php.net>
Sat, 27 Jan 2007 18:27:19 +0000 (18:27 +0000)
committerGreg Beaver <cellog@php.net>
Sat, 27 Jan 2007 18:27:19 +0000 (18:27 +0000)
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c

index eafe3d150e7fbfaee27687eb89dce27dd4d753f0..bc1f08135a62c705321bd2840979a020cce0c21e 100644 (file)
@@ -246,7 +246,7 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa
  * Retrieve a copy of the file information on a single file within a phar, or null.
  * This also transfers the open file pointer, if any, to the entry.
  */
-static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC) /* {{{ */
+static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
        phar_entry_info *entry;
@@ -259,18 +259,26 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len
                return FAILURE;
        }
        *ret = NULL;
+       *error = (char *) emalloc(200 + fname_len);
+       **error = '\0';
        if (for_write && PHAR_G(readonly)) {
-               php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for writing, disabled by ini setting", fname);
+               if (error) {
+                       sprintf(*error, "phar error: file \"%s\" cannot opened for writing, disabled by ini setting", fname);
+               }
                return FAILURE;
        }
        if ((phar = phar_get_archive(fname, fname_len, NULL, 0 TSRMLS_CC)) != NULL) {
                if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) != NULL) {
                        if (entry->is_modified && !for_write) {
-                               php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for reading, writable file pointers are open", fname);
+                               if (error) {
+                                       sprintf(*error, "phar error: file \"%s\" cannot opened for reading, writable file pointers are open", fname);
+                               }
                                return FAILURE;
                        }
                        if (entry->fp_refcount && for_write) {
-                               php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "phar error: file \"%s\" cannot opened for writing, readable file pointers are open", fname);
+                               if (error) {
+                                       sprintf(*error, "phar error: file \"%s\" cannot opened for writing, readable file pointers are open", fname);
+                               }
                                return FAILURE;
                        }
                        if (entry->is_deleted) {
@@ -363,7 +371,7 @@ void phar_entry_remove(phar_entry_data *idata TSRMLS_DC) /* {{{ */
 /**
  * Create a new dummy file slot within a writeable phar for a newly created file
  */
-phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC) /* {{{ */
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
        phar_entry_info *entry, etemp;
@@ -373,7 +381,7 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char
                return NULL;
        }
 
-       if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode TSRMLS_CC)) {
+       if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, path_len, mode, error TSRMLS_CC)) {
                return NULL;
        }
        if (ret) {
@@ -1260,6 +1268,7 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
        phar_entry_data *idata;
        char *internal_file;
        char *buffer;
+       char *error;
        char *filter_name;
        char tmpbuf[8];
        php_url *resource = NULL;
@@ -1290,12 +1299,17 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
        /* strip leading "/" */
        internal_file = estrdup(resource->path + 1);
        if (mode[0] == 'w' || (mode[0] == 'r' && mode[1] == '+')) {
-               if (NULL == (idata = phar_get_or_create_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file), mode TSRMLS_CC))) {
+               if (NULL == (idata = phar_get_or_create_entry_data(resource->host, strlen(resource->host), internal_file, strlen(internal_file), mode, &error TSRMLS_CC))) {
+                       if (error[0]) {
+                               php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
+                       }
+                       efree(error);
                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: file \"%s\" could not be created in phar \"%s\"", internal_file, resource->host);
                        efree(internal_file);
                        php_url_free(resource);
                        return NULL;
                }
+               efree(error);
                fpf = php_stream_alloc(&phar_ops, idata, NULL, mode);
                php_url_free(resource);
                efree(internal_file);
@@ -1312,12 +1326,18 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, char *pat
                }
                return fpf;
        } else {
-               if ((FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r" TSRMLS_CC)) || !idata) {
+               if ((FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) || !idata) {
+                       if (error[0]) {
+                               php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
+                       }
+                       efree(error);
                        php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\"", internal_file, resource->host);
                        efree(internal_file);
                        php_url_free(resource);
                        return NULL;
                }
+               /* alloced in get_entry_data */
+               efree(error);
        }
        php_url_free(resource);
        
@@ -2416,6 +2436,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
 {
        php_url *resource;
        char *internal_file;
+       char *error;
        phar_entry_data *idata;
        
        resource = php_url_parse(url);
@@ -2445,12 +2466,17 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
        
        /* need to copy to strip leading "/", will get touched again */
        internal_file = estrdup(resource->path + 1);
-       if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r" TSRMLS_CC)) {
+       if (FAILURE == phar_get_entry_data(&idata, resource->host, strlen(resource->host), internal_file, strlen(internal_file), "r", &error TSRMLS_CC)) {
                /* constraints of fp refcount were not met */
+               if (error[0]) {
+                       php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, error);
+               }
+               efree(error);
                efree(internal_file);
                php_url_free(resource);
                return FAILURE;
        }
+       efree(error);
        if (!idata) {
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar error: \"%s\" is not a file in phar \"%s\", cannot unlink", internal_file, resource->host);
                efree(internal_file);
@@ -2467,6 +2493,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, char *url, int optio
                phar_entry_delref(idata TSRMLS_CC);
                return FAILURE;
        }
+       php_url_free(resource);
        efree(internal_file);
        phar_entry_remove(idata TSRMLS_CC);
        return SUCCESS;
index a3d7e839d9ca27d078858dfbcdd17cbb32d251f7..2ad55ace6152f8811d5579d6a03991a792f9aafe 100755 (executable)
@@ -249,7 +249,7 @@ int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);
 
 void phar_destroy_phar_data(phar_archive_data *data TSRMLS_DC);
 phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len TSRMLS_DC);
-phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode TSRMLS_DC);
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char *path, int path_len, char *mode, char **error TSRMLS_DC);
 int phar_flush(phar_archive_data *archive, char *user_stub, long len TSRMLS_DC);
 int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC);
 
index 63e8679eebfd17154513f967ed4496a4250e8b13..2720618a91f12cafac3022b2b0597f3086bfa9fa 100755 (executable)
@@ -343,6 +343,7 @@ PHP_METHOD(Phar, offsetGet)
 PHP_METHOD(Phar, offsetSet)
 {
        char *fname;
+       char *error;
        int fname_len;
        zval *contents;
        long contents_len = PHP_STREAM_COPY_ALL;
@@ -363,9 +364,11 @@ PHP_METHOD(Phar, offsetSet)
        if (Z_TYPE_P(contents) != IS_STRING && Z_TYPE_P(contents) != IS_RESOURCE) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s could not be written to", fname);
        }
-       if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b" TSRMLS_CC))) {
-               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created", fname);
+       if (!(data = phar_get_or_create_entry_data(phar_obj->arc.archive->fname, phar_obj->arc.archive->fname_len, fname, fname_len, "w+b", &error TSRMLS_CC))) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", fname, error);
+               efree(error);
        } else {
+               efree(error);
                if (Z_TYPE_P(contents) == IS_STRING) {
                        contents_len = php_stream_write(data->fp, Z_STRVAL_P(contents), Z_STRLEN_P(contents));
                        if (contents_len != Z_STRLEN_P(contents)) {