From: Greg Beaver Date: Tue, 6 Feb 2007 17:09:37 +0000 (+0000) Subject: fix several potential segfaults, add tests for chmod(), fix chmod() X-Git-Tag: RELEASE_1_0_0RC1~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc17dcfcd121041095b9bd0a27fd0fe70e6a4953;p=php fix several potential segfaults, add tests for chmod(), fix chmod() --- diff --git a/ext/phar/phar.c b/ext/phar/phar.c index c85e2c0068..c765423788 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1900,13 +1900,14 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err php_serialize_data_t metadata_hash; smart_str metadata_str = {0}; + if (error) { + *error = NULL; + } + if (PHAR_G(readonly)) { return EOF; } - if (error) { - *error = NULL; - } if (archive->fp && !archive->is_brandnew) { oldfile = archive->fp; closeoldfile = 0; @@ -1959,6 +1960,10 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err } else { if ((pos = strstr(user_stub, "__HALT_COMPILER();")) == NULL) { + if (closeoldfile) { + php_stream_close(oldfile); + } + php_stream_close(newfile); if (error) { spprintf(error, 0, "illegal stub for phar \"%s\"", archive->fname); } @@ -2277,10 +2282,20 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err if (entry->cfp) { file = entry->cfp; php_stream_rewind(file); - } else if (entry->is_modified || !oldfile) { + } else if (entry->fp && (entry->is_modified || !oldfile)) { file = entry->fp; php_stream_rewind(file); } else { + if (!oldfile) { + if (closeoldfile) { + php_stream_close(oldfile); + } + php_stream_close(newfile); + if (error) { + spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, archive->fname); + } + return EOF; + } if (-1 == php_stream_seek(oldfile, entry->offset_within_phar + archive->internal_file_start, SEEK_SET)) { if (closeoldfile) { php_stream_close(oldfile); @@ -2399,6 +2414,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err } else { archive->fp = php_stream_open_wrapper(archive->fname, "w+b", IGNORE_URL|STREAM_MUST_SEEK|REPORT_ERRORS, NULL); if (!archive->fp) { + php_stream_close(newfile); archive->fp = newfile; if (error) { spprintf(error, 0, "unable to open new phar \"%s\" for writing", archive->fname); @@ -2414,6 +2430,7 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err if (error) { spprintf(error, 0, "unable to seek to __HALT_COMPILER(); in new phar \"%s\"", archive->fname); } + php_stream_close(newfile); return EOF; } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index d619a21917..9c6092c0ab 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -35,6 +35,7 @@ #include "zend_qsort.h" #include "main/php_streams.h" #include "ext/standard/info.h" +#include "ext/standard/basic_functions.h" #include "ext/standard/url.h" #include "ext/standard/crc32.h" #include "ext/standard/md5.h" diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 3b1dc2adbe..e3d4c23f0e 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -885,9 +885,13 @@ PHP_METHOD(PharFileInfo, getPharFlags) */ PHP_METHOD(PharFileInfo, chmod) { + char *error; long perms; PHAR_ENTRY_OBJECT(); + if (PHAR_G(readonly)) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Cannot modify permissions for file \"%s\" write operations are prohibited", entry_obj->ent.entry->filename, entry_obj->ent.entry->phar->fname); + } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perms) == FAILURE) { return; } @@ -895,6 +899,24 @@ PHP_METHOD(PharFileInfo, chmod) entry_obj->ent.entry->flags &= ~PHAR_ENT_PERM_MASK; perms &= 0777; entry_obj->ent.entry->flags |= perms; + entry_obj->ent.entry->phar->is_modified = 1; + entry_obj->ent.entry->is_modified = 1; + /* hackish cache in php_stat needs to be cleared */ + /* if this code fails to work, check main/streams/streams.c, _php_stream_stat_path */ + if (BG(CurrentLStatFile)) { + efree(BG(CurrentLStatFile)); + } + if (BG(CurrentStatFile)) { + efree(BG(CurrentStatFile)); + } + BG(CurrentLStatFile) = NULL; + BG(CurrentStatFile) = NULL; + + phar_flush(entry_obj->ent.entry->phar, 0, 0, &error TSRMLS_CC); + if (error) { + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, error); + efree(error); + } } /* }}} */ diff --git a/ext/phar/tests/033.phpt b/ext/phar/tests/033.phpt new file mode 100644 index 0000000000..ddcc36ae54 --- /dev/null +++ b/ext/phar/tests/033.phpt @@ -0,0 +1,33 @@ +--TEST-- +Phar::chmod +--SKIPIF-- + +--INI-- +phar.readonly=0 +phar.require_hash=0 +--FILE-- +'; + +$files = array(); +$files['a.php'] = ''; +include 'phar_test.inc'; +$a = new Phar($fname); +var_dump($a['a.php']->isExecutable()); +$a['a.php']->chmod(0777); +var_dump($a['a.php']->isExecutable()); +$a['a.php']->chmod(0666); +var_dump($a['a.php']->isExecutable()); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(false) +bool(true) +bool(false) +===DONE=== diff --git a/ext/phar/tests/033a.phpt b/ext/phar/tests/033a.phpt new file mode 100644 index 0000000000..b2a8c51837 --- /dev/null +++ b/ext/phar/tests/033a.phpt @@ -0,0 +1,35 @@ +--TEST-- +Phar::chmod +--SKIPIF-- + +--INI-- +phar.require_hash=0 +--FILE-- +'; + +$files = array(); +$files['a.php'] = ''; +include 'phar_test.inc'; +try { + $a = new Phar($fname); + var_dump($a['a.php']->isExecutable()); + $a['a.php']->chmod(0777); + var_dump($a['a.php']->isExecutable()); + $a['a.php']->chmod(0666); + var_dump($a['a.php']->isExecutable()); +} catch (Exception $e) { + echo $e->getMessage() . "\n"; +} +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(false) +Cannot modify permissions for file "a.php" write operations are prohibited +===DONE===