]> granicus.if.org Git - php/commitdiff
fix invalid free
authorGreg Beaver <cellog@php.net>
Sun, 27 Apr 2008 07:04:56 +0000 (07:04 +0000)
committerGreg Beaver <cellog@php.net>
Sun, 27 Apr 2008 07:04:56 +0000 (07:04 +0000)
ext/phar/phar.c
ext/phar/tar.c
ext/phar/tests/phar_extract.phpt
ext/phar/zip.c

index 9629eb62bed0ae63cd3891301665e19f710b19ab..b746190bcf3778a1449f2f405acba18330abf8f8 100644 (file)
@@ -2061,7 +2061,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
        php_stream_filter *filter;
        php_serialize_data_t metadata_hash;
        smart_str main_metadata_str = {0};
-       int free_user_stub;
+       int free_user_stub, free_fp = 1, free_ufp = 1;
 
        if (error) {
                *error = NULL;
@@ -2229,6 +2229,18 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
                        /* remove this from the new phar */
                        continue;
                }
+               if (!entry->is_modified && entry->fp_refcount) {
+                       /* open file pointers refer to this fp, do not free the stream */
+                       switch (entry->fp_type) {
+                               case PHAR_FP:
+                                       free_fp = 0;
+                                       break;
+                               case PHAR_UFP:
+                                       free_ufp = 0;
+                               default:
+                                       break;
+                       }
+               }
                /* after excluding deleted files, calculate manifest size in bytes and number of entries */
                ++new_manifest_count;
 
@@ -2655,11 +2667,13 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
        /* finally, close the temp file, rename the original phar,
           move the temp to the old phar, unlink the old phar, and reload it into memory
        */
-       if (phar->fp) {
+       if (phar->fp && free_fp) {
                php_stream_close(phar->fp);
        }
        if (phar->ufp) {
-               php_stream_close(phar->ufp);
+               if (free_ufp) {
+                       php_stream_close(phar->ufp);
+               }
                phar->ufp = NULL;
        }
        if (closeoldfile) {
index bf607637229d2a88ad293a824422af87f00648d1..eeb8c2a7051b98a13924f908b1dc0b2015656f46 100644 (file)
@@ -404,6 +404,8 @@ int phar_open_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, i
 struct _phar_pass_tar_info {
        php_stream *old;
        php_stream *new;
+       int free_fp;
+       int free_ufp;
        char **error;
 };
 
@@ -492,6 +494,18 @@ int phar_tar_writeheaders(void *pDest, void *argument TSRMLS_DC)
                memset(padding, 0, 512);
                php_stream_write(fp->new, padding, ((entry->uncompressed_filesize +511)&~511) - entry->uncompressed_filesize);
        }
+       if (!entry->is_modified && entry->fp_refcount) {
+               /* open file pointers refer to this fp, do not free the stream */
+               switch (entry->fp_type) {
+                       case PHAR_FP:
+                               fp->free_fp = 0;
+                               break;
+                       case PHAR_UFP:
+                               fp->free_ufp = 0;
+                       default:
+                               break;
+               }
+       }
 
        entry->is_modified = 0;
        if (entry->fp_type == PHAR_MOD && entry->fp != entry->phar->fp && entry->fp != entry->phar->ufp) {
@@ -676,6 +690,8 @@ nostub:
        pass.old = oldfile;
        pass.new = newfile;
        pass.error = error;
+       pass.free_fp = 1;
+       pass.free_ufp = 1;
 
        zend_hash_apply_with_argument(&phar->manifest, (apply_func_arg_t) phar_tar_writeheaders, (void *) &pass TSRMLS_CC);
 
@@ -692,11 +708,13 @@ nostub:
                php_stream_close(newfile);
                return EOF;
        }
-       if (phar->fp) {
+       if (phar->fp && pass.free_fp) {
                php_stream_close(phar->fp);
        }
        if (phar->ufp) {
-               php_stream_close(phar->ufp);
+               if (pass.free_ufp) {
+                       php_stream_close(phar->ufp);
+               }
                phar->ufp = NULL;
        }
 
index 6f464f0768faedcffb7523e34b86f6ebcee603f0..1606aa60fdab06498d1f45330b37b18543ee5676 100644 (file)
@@ -34,7 +34,7 @@ $a->extractTo(dirname(__FILE__) . '/extract2', array('file2.txt', 'one/level'));
 var_dump(file_get_contents(dirname(__FILE__) . '/extract2/file2.txt'));
 var_dump(is_dir(dirname(__FILE__) . '/extract2/one/level'));
 try {
-$a->extractTo('whatever', 134);
+$a->extractTo(dirname(__FILE__) . '/whatever', 134);
 } catch (Exception $e) {
 echo $e->getMessage(), "\n";
 }
@@ -79,6 +79,7 @@ echo $e->getMessage(), "\n";
 ===DONE===
 --CLEAN--
 <?php
+@rmdir(dirname(__FILE__) . '/whatever');
 @unlink(dirname(__FILE__) . '/oops');
 @rmdir(dirname(__FILE__) . '/oops1');
 @unlink(dirname(__FILE__) . '/tempmanifest1.phar.php');
index 37c1a19787c5e9415b8d1a5a1079c342f862aae9..a436b8836cb7ee08b8ab7abdcfb41dbaa6fc20f6 100644 (file)
@@ -487,6 +487,8 @@ struct _phar_zip_pass {
        php_stream *filefp;
        php_stream *centralfp;
        php_stream *old;
+       int free_fp;
+       int free_ufp;
        char **error;
 };
 /* perform final modification of zip contents for each file in the manifest before saving */
@@ -703,6 +705,18 @@ continue_dir:
                }
                entry->is_modified = 0;
        } else {
+               if (entry->fp_refcount) {
+                       /* open file pointers refer to this fp, do not free the stream */
+                       switch (entry->fp_type) {
+                               case PHAR_FP:
+                                       p->free_fp = 0;
+                                       break;
+                               case PHAR_UFP:
+                                       p->free_ufp = 0;
+                               default:
+                                       break;
+                       }
+               }
                if (!entry->is_dir && entry->compressed_filesize && entry->compressed_filesize != php_stream_copy_to_stream(p->old, p->filefp, entry->compressed_filesize)) {
                        spprintf(p->error, 0, "unable to copy contents of file \"%s\" while creating zip-based phar \"%s\"", entry->filename, entry->phar->fname);
                        return ZEND_HASH_APPLY_STOP;
@@ -916,6 +930,7 @@ nostub:
                }
                return EOF;
        }
+       pass.free_fp = pass.free_ufp = 1;
        memset(&eocd, 0, sizeof(eocd));
 
        strncpy(eocd.signature, "PK\5\6", 4);
@@ -978,11 +993,13 @@ nostub:
                }
                smart_str_free(&main_metadata_str);
        }
-       if (phar->fp) {
+       if (phar->fp && pass.free_fp) {
                php_stream_close(phar->fp);
        }
        if (phar->ufp) {
-               php_stream_close(phar->ufp);
+               if (pass.free_ufp) {
+                       php_stream_close(phar->ufp);
+               }
                phar->ufp = NULL;
        }
        /* re-open */