From: Greg Beaver Date: Sun, 27 Apr 2008 07:04:56 +0000 (+0000) Subject: fix invalid free X-Git-Tag: RELEASE_2_0_0b1~181 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5bf3d1d362042d445ba0b6aa0fdda61736582cc5;p=php fix invalid free --- diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 9629eb62be..b746190bcf 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -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) { diff --git a/ext/phar/tar.c b/ext/phar/tar.c index bf60763722..eeb8c2a705 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -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; } diff --git a/ext/phar/tests/phar_extract.phpt b/ext/phar/tests/phar_extract.phpt index 6f464f0768..1606aa60fd 100644 --- a/ext/phar/tests/phar_extract.phpt +++ b/ext/phar/tests/phar_extract.phpt @@ -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-- 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 */