]> granicus.if.org Git - php/commitdiff
fix several potential segfaults, add tests for chmod(), fix chmod()
authorGreg Beaver <cellog@php.net>
Tue, 6 Feb 2007 17:09:37 +0000 (17:09 +0000)
committerGreg Beaver <cellog@php.net>
Tue, 6 Feb 2007 17:09:37 +0000 (17:09 +0000)
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/tests/033.phpt [new file with mode: 0644]
ext/phar/tests/033a.phpt [new file with mode: 0644]

index c85e2c00687c3e6b82eb629e67425ab032fca9a5..c765423788ffc0ac75b97c9c25ea9781dfae3f12 100644 (file)
@@ -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;
        }
 
index d619a21917906655090f29b3cf5e38a4150b9730..9c6092c0abddb7684a49dd09d12409bd05fa206d 100755 (executable)
@@ -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"
index 3b1dc2adbee90ad6e2c5c47f904b50883474f475..e3d4c23f0e1a1621bd1b3d8c01f7cb3d3cb5575f 100755 (executable)
@@ -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 (file)
index 0000000..ddcc36a
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Phar::chmod
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.1.phar.php';
+$pname = 'phar://hio';
+$file = '<?php include "' . $pname . '/a.php"; __HALT_COMPILER(); ?>';
+
+$files = array();
+$files['a.php']   = '<?php echo "This is a\n"; include "'.$pname.'/b.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--
+<?php 
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.phar.php');
+?>
+--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 (file)
index 0000000..b2a8c51
--- /dev/null
@@ -0,0 +1,35 @@
+--TEST--
+Phar::chmod
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+--INI--
+phar.require_hash=0
+--FILE--
+<?php
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.1.phar.php';
+$pname = 'phar://hio';
+$file = '<?php include "' . $pname . '/a.php"; __HALT_COMPILER(); ?>';
+
+$files = array();
+$files['a.php']   = '<?php echo "This is a\n"; include "'.$pname.'/b.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--
+<?php 
+unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.1.phar.php');
+?>
+--EXPECTF--
+bool(false)
+Cannot modify permissions for file "a.php" write operations are prohibited
+===DONE===