cellog          Thu May 15 16:09:21 2008 UTC

  Modified files:              
    /php-src/ext/phar   dirstream.c phar_internal.h phar_object.c 
                        stream.c util.c 
    /php-src/ext/phar/tests     phar_extract2.phpt phar_offset_check.phpt 
                                030.phpt addfuncs.phpt mkdir.phpt 
                                mounteddir.phpt 
                                phar_buildfromiterator4.phpt phar_copy.phpt 
                                phar_offset_get_error.phpt zf_test.phpt 
    /php-src/ext/phar/tests/tar dir.phpt tar_003.phpt 
  Log:
  MFB: plug security hole of unfettered creation access to .phar magic directory
  
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/dirstream.c?r1=1.28&r2=1.29&diff_format=u
Index: php-src/ext/phar/dirstream.c
diff -u php-src/ext/phar/dirstream.c:1.28 php-src/ext/phar/dirstream.c:1.29
--- php-src/ext/phar/dirstream.c:1.28   Wed May 14 21:27:31 2008
+++ php-src/ext/phar/dirstream.c        Thu May 15 16:09:21 2008
@@ -196,8 +196,9 @@
        ALLOC_HASHTABLE(data);
        zend_hash_init(data, 64, zend_get_hash_value, NULL, 0);
 
-       if (*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) {
+       if ((*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) || 
(dirlen >= sizeof(".phar")-1 && !memcmp(dir, ".phar", sizeof(".phar")-1))) {
                /* make empty root directory for empty phar */
+               /* make empty directory for .phar magic directory */
                efree(dir);
                return php_stream_alloc(&phar_dir_ops, data, NULL, "r");
        }
@@ -217,6 +218,13 @@
                }
                if (*dir == '/') {
                        /* root directory */
+                       if (keylen >= sizeof(".phar")-1 && !memcmp(str_key, 
".phar", sizeof(".phar")-1)) {
+                               /* do not add any magic entries to this 
directory */
+                               if (SUCCESS != 
zend_hash_move_forward(manifest)) {
+                                       break;
+                               }
+                               continue;
+                       }
                        if (NULL != (found = (char *) memchr(str_key, '/', 
keylen))) {
                                /* the entry has a path separator and is a 
subdirectory */
                                entry = (char *) safe_emalloc(found - str_key, 
1, 1);
@@ -446,7 +454,7 @@
                return FAILURE;
        }
 
-       if ((e = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path + 1), 2, &error TSRMLS_CC))) {
+       if ((e = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path + 1), 2, &error, 1 TSRMLS_CC))) {
                /* directory exists, or is a subdirectory of an existing file */
                if (e->is_temp_dir) {
                        efree(e->filename);
@@ -462,7 +470,7 @@
                php_url_free(resource);
                return FAILURE;
        }
-       if ((e = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path + 1), 0, &error TSRMLS_CC))) {
+       if ((e = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path + 1), 0, &error, 1 TSRMLS_CC))) {
                /* entry exists as a file */
                php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "phar 
error: cannot create directory \"%s\" in phar \"%s\", file already exists", 
resource->path+1, resource->host);
                php_url_free(resource);
@@ -565,7 +573,7 @@
                return FAILURE;
        }
 
-       if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path) - 1, 2, &error TSRMLS_CC))) {
+       if (!(entry = phar_get_entry_info_dir(phar, resource->path + 1, 
strlen(resource->path) - 1, 2, &error, 1 TSRMLS_CC))) {
                if (error) {
                        php_stream_wrapper_log_error(wrapper, options 
TSRMLS_CC, "phar error: cannot remove directory \"%s\" in phar \"%s\", %s", 
resource->path+1, resource->host, error);
                        efree(error);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_internal.h?r1=1.110&r2=1.111&diff_format=u
Index: php-src/ext/phar/phar_internal.h
diff -u php-src/ext/phar/phar_internal.h:1.110 
php-src/ext/phar/phar_internal.h:1.111
--- php-src/ext/phar/phar_internal.h:1.110      Wed May 14 21:27:31 2008
+++ php-src/ext/phar/phar_internal.h    Thu May 15 16:09:21 2008
@@ -17,7 +17,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: phar_internal.h,v 1.110 2008/05/14 21:27:31 sfox Exp $ */
+/* $Id: phar_internal.h,v 1.111 2008/05/15 16:09:21 cellog Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -445,10 +445,10 @@
 int phar_archive_delref(phar_archive_data *phar TSRMLS_DC);
 int phar_entry_delref(phar_entry_data *idata TSRMLS_DC);
 
-phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int 
path_len, char **error TSRMLS_DC);
-phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, 
int path_len, char dir, char **error TSRMLS_DC);
-phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC);
-int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC);
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int 
path_len, char **error, int security TSRMLS_DC);
+phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, 
int path_len, char dir, char **error, int security TSRMLS_DC);
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error, int 
security TSRMLS_DC);
+int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error, int 
security TSRMLS_DC);
 int phar_flush(phar_archive_data *archive, char *user_stub, long len, int 
convert, char **error TSRMLS_DC);
 int phar_detect_phar_fname_ext(const char *filename, int check_length, const 
char **ext_str, int *ext_len, int executable, int for_create, int is_complete 
TSRMLS_DC);
 int phar_split_fname(char *filename, int filename_len, char **arch, int 
*arch_len, char **entry, int *entry_len, int executable, int for_create 
TSRMLS_DC);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_object.c?r1=1.268&r2=1.269&diff_format=u
Index: php-src/ext/phar/phar_object.c
diff -u php-src/ext/phar/phar_object.c:1.268 
php-src/ext/phar/phar_object.c:1.269
--- php-src/ext/phar/phar_object.c:1.268        Wed May 14 21:27:31 2008
+++ php-src/ext/phar/phar_object.c      Thu May 15 16:09:21 2008
@@ -17,7 +17,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: phar_object.c,v 1.268 2008/05/14 21:27:31 sfox Exp $ */
+/* $Id: phar_object.c,v 1.269 2008/05/15 16:09:21 cellog Exp $ */
 
 #include "phar_internal.h"
 #include "func_interceptors.h"
@@ -327,7 +327,7 @@
        phar_entry_data *phar;
        char *error;
        if (f404_len) {
-               if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, 
f404, f404_len, "r", 0, &error TSRMLS_CC)) {
+               if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, 
f404, f404_len, "r", 0, &error, 1 TSRMLS_CC)) {
                        if (error) {
                                efree(error);
                        }
@@ -672,7 +672,7 @@
                        entry = estrndup("/index.php", sizeof("/index.php"));
                        entry_len = sizeof("/index.php")-1;
                }
-               if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, 
entry, entry_len, "r", 0, NULL TSRMLS_CC)) {
+               if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, 
entry, entry_len, "r", 0, NULL, 1 TSRMLS_CC)) {
                        phar_do_404(fname, fname_len, f404, f404_len, entry, 
entry_len TSRMLS_CC);
                        if (free_pathinfo) {
                                efree(path_info);
@@ -711,7 +711,7 @@
                }
        }
 
-       if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, 
entry_len, "r", 0, &error TSRMLS_CC)) {
+       if (FAILURE == phar_get_entry_data(&phar, fname, fname_len, entry, 
entry_len, "r", 0, &error, 1 TSRMLS_CC)) {
                phar_do_404(fname, fname_len, f404, f404_len, entry, entry_len 
TSRMLS_CC);
 #ifdef PHP_WIN32
                efree(fname);
@@ -1503,12 +1503,31 @@
        }
 
 after_open_fp:
-       if (!(data = 
phar_get_or_create_entry_data(phar_obj->arc.archive->fname, 
phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", 0, &error 
TSRMLS_CC))) {
+       if (str_key_len >= sizeof(".phar")-1 && !memcmp(str_key, ".phar", 
sizeof(".phar")-1)) {
+               /* silently skip any files that would be added to the magic 
.phar directory */
+               if (save) {
+                       efree(save);
+               }
+               if (temp) {
+                       efree(temp);
+               }
+               if (opened) {
+                       efree(opened);
+               }
+               if (close_fp) {
+                       php_stream_close(fp);
+               }
+               return ZEND_HASH_APPLY_KEEP;
+       }
+       if (!(data = 
phar_get_or_create_entry_data(phar_obj->arc.archive->fname, 
phar_obj->arc.archive->fname_len, str_key, str_key_len, "w+b", 0, &error, 1 
TSRMLS_CC))) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Entry %s cannot be created: %s", str_key, error);
                efree(error);
                if (save) {
                        efree(save);
                }
+               if (opened) {
+                       efree(opened);
+               }
                if (temp) {
                        efree(temp);
                }
@@ -2992,6 +3011,20 @@
                RETURN_FALSE;
        }
 
+       if (oldfile_len >= sizeof(".phar")-1 && !memcmp(oldfile, ".phar", 
sizeof(".phar")-1)) {
+               /* can't copy a meta file */
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 
TSRMLS_CC,
+                       "file \"%s\" cannot be copied to file \"%s\", cannot 
copy Phar meta-file in %s", oldfile, newfile, phar_obj->arc.archive->fname);
+               RETURN_FALSE;
+       }
+
+       if (newfile_len >= sizeof(".phar")-1 && !memcmp(newfile, ".phar", 
sizeof(".phar")-1)) {
+               /* can't copy a meta file */
+               zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 
TSRMLS_CC,
+                       "file \"%s\" cannot be copied to file \"%s\", cannot 
copy to Phar meta-file in %s", oldfile, newfile, phar_obj->arc.archive->fname);
+               RETURN_FALSE;
+       }
+
        if (!zend_hash_exists(&phar_obj->arc.archive->manifest, oldfile, (uint) 
oldfile_len) || SUCCESS != zend_hash_find(&phar_obj->arc.archive->manifest, 
oldfile, (uint) oldfile_len, (void**)&oldentry) || oldentry->is_deleted) {
                zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 
TSRMLS_CC,
                        "file \"%s\" cannot be copied to file \"%s\", file does 
not exist in %s", oldfile, newfile, phar_obj->arc.archive->fname);
@@ -3077,6 +3110,11 @@
                                RETURN_FALSE;
                        }
                }
+
+               if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", 
sizeof(".phar")-1)) {
+                       /* none of these are real files, so they don't exist */
+                       RETURN_FALSE;
+               }
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
@@ -3098,10 +3136,26 @@
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &fname, 
&fname_len) == FAILURE) {
                return;
        }
-       
-       if (!(entry = phar_get_entry_info_dir(phar_obj->arc.archive, fname, 
fname_len, 1, &error TSRMLS_CC))) {
+
+       /* security is 0 here so that we can get a better error message than 
"entry doesn't exist" */
+       if (!(entry = phar_get_entry_info_dir(phar_obj->arc.archive, fname, 
fname_len, 1, &error, 0 TSRMLS_CC))) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:"");
        } else {
+               if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, 
".phar/stub.php", sizeof(".phar/stub.php")-1)) {
+                       zend_throw_exception_ex(spl_ce_BadMethodCallException, 
0 TSRMLS_CC, "Cannot get stub \".phar/stub.php\" directly in phar \"%s\", use 
getStub", phar_obj->arc.archive->fname);
+                       return;
+               }
+       
+               if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, 
".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
+                       zend_throw_exception_ex(spl_ce_BadMethodCallException, 
0 TSRMLS_CC, "Cannot get alias \".phar/alias.txt\" directly in phar \"%s\", use 
getAlias", phar_obj->arc.archive->fname);
+                       return;
+               }
+       
+               if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", 
sizeof(".phar")-1)) {
+                       zend_throw_exception_ex(spl_ce_BadMethodCallException, 
0 TSRMLS_CC, "Cannot directly get any files or directories in magic \".phar\" 
directory", phar_obj->arc.archive->fname);
+                       return;
+               }
+
                if (entry->is_temp_dir) {
                        efree(entry->filename);
                        efree(entry);
@@ -3125,7 +3179,12 @@
        phar_entry_data *data;
        php_stream *contents_file;
 
-       if (!(data = phar_get_or_create_entry_data(phar->fname, 
phar->fname_len, filename, filename_len, "w+b", 0, &error TSRMLS_CC))) {
+       if (filename_len >= sizeof(".phar")-1 && !memcmp(filename, ".phar", 
sizeof(".phar")-1)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Cannot create any files in magic \".phar\" directory", phar->fname);
+               return;
+       }
+
+       if (!(data = phar_get_or_create_entry_data(phar->fname, 
phar->fname_len, filename, filename_len, "w+b", 0, &error, 1 TSRMLS_CC))) {
                if (error) {
                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 
0 TSRMLS_CC, "Entry %s does not exist and cannot be created: %s", filename, 
error);
                        efree(error);
@@ -3170,7 +3229,7 @@
        char *error;
        phar_entry_data *data;
 
-       if (!(data = phar_get_or_create_entry_data(phar->fname, 
phar->fname_len, dirname, dirname_len, "w+b", 2, &error TSRMLS_CC))) {
+       if (!(data = phar_get_or_create_entry_data(phar->fname, 
phar->fname_len, dirname, dirname_len, "w+b", 2, &error, 1 TSRMLS_CC))) {
                if (error) {
                        zend_throw_exception_ex(spl_ce_BadMethodCallException, 
0 TSRMLS_CC, "Directory %s does not exist and cannot be created: %s", dirname, 
error);
                        efree(error);
@@ -3213,15 +3272,20 @@
                return;
        }
 
-       if ((phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip) && 
fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, ".phar/stub.php", 
sizeof(".phar/stub.php")-1)) {
+       if (fname_len == sizeof(".phar/stub.php")-1 && !memcmp(fname, 
".phar/stub.php", sizeof(".phar/stub.php")-1)) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Cannot set stub \".phar/stub.php\" directly in phar \"%s\", use 
setStub", phar_obj->arc.archive->fname);
                return;
        }
 
-       if ((phar_obj->arc.archive->is_tar || phar_obj->arc.archive->is_zip) && 
fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, ".phar/alias.txt", 
sizeof(".phar/alias.txt")-1)) {
+       if (fname_len == sizeof(".phar/alias.txt")-1 && !memcmp(fname, 
".phar/alias.txt", sizeof(".phar/alias.txt")-1)) {
                zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Cannot set alias \".phar/alias.txt\" directly in phar \"%s\", use 
setAlias", phar_obj->arc.archive->fname);
                return;
        }
+
+       if (fname_len >= sizeof(".phar")-1 && !memcmp(fname, ".phar", 
sizeof(".phar")-1)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Cannot set any files or directories in magic \".phar\" directory", 
phar_obj->arc.archive->fname);
+               return;
+       }
        phar_add_file(phar_obj->arc.archive, fname, fname_len, cont_str, 
cont_len, zresource TSRMLS_CC);
 }
 /* }}} */
@@ -3280,6 +3344,10 @@
                return;
        }
 
+       if (dirname_len >= sizeof(".phar")-1 && !memcmp(dirname, ".phar", 
sizeof(".phar")-1)) {
+               zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 
TSRMLS_CC, "Cannot create a directory in magic \".phar\" directory");
+               return;
+       }
        phar_mkdir(phar_obj->arc.archive, dirname, dirname_len TSRMLS_CC);
 }
 /* }}} */
@@ -3548,6 +3616,9 @@
                /* silently ignore mounted entries */
                return SUCCESS;
        }
+       if (entry->filename_len >= sizeof(".phar")-1 && 
!memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
+               return SUCCESS;
+       }
        len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
        if (len >= MAXPATHLEN) {
                char *tmp;
@@ -3834,7 +3905,7 @@
                return;
        }
 
-       if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 
1, &error TSRMLS_CC)) == NULL) {
+       if ((entry_info = phar_get_entry_info_dir(phar_data, entry, entry_len, 
1, &error, 1 TSRMLS_CC)) == NULL) {
                zend_throw_exception_ex(spl_ce_RuntimeException, 0 TSRMLS_CC,
                        "Cannot access phar file entry '%s' in archive 
'%s'%s%s", entry, arch, error?", ":"", error?error:"");
                efree(arch);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/stream.c?r1=1.29&r2=1.30&diff_format=u
Index: php-src/ext/phar/stream.c
diff -u php-src/ext/phar/stream.c:1.29 php-src/ext/phar/stream.c:1.30
--- php-src/ext/phar/stream.c:1.29      Wed May 14 21:27:31 2008
+++ php-src/ext/phar/stream.c   Thu May 15 16:09:21 2008
@@ -178,7 +178,7 @@
        /* 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, host_len, internal_file, 
strlen(internal_file), mode, 0, &error TSRMLS_CC))) {
+               if (NULL == (idata = 
phar_get_or_create_entry_data(resource->host, host_len, internal_file, 
strlen(internal_file), mode, 0, &error, 1 TSRMLS_CC))) {
                        if (error) {
                                php_stream_wrapper_log_error(wrapper, options 
TSRMLS_CC, error);
                                efree(error);
@@ -223,7 +223,8 @@
                }
                return fpf;
        } else {
-               if ((FAILURE == phar_get_entry_data(&idata, resource->host, 
host_len, internal_file, strlen(internal_file), "r", 0, &error TSRMLS_CC)) || 
!idata) {
+               /* read-only access is allowed to magic files in .phar 
directory */
+               if ((FAILURE == phar_get_entry_data(&idata, resource->host, 
host_len, internal_file, strlen(internal_file), "r", 0, &error, 0 TSRMLS_CC)) 
|| !idata) {
                        if (error) {
                                php_stream_wrapper_log_error(wrapper, options 
TSRMLS_CC, error);
                                efree(error);
@@ -675,7 +676,7 @@
 
        /* 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", 0, &error 
TSRMLS_CC)) {
+       if (FAILURE == phar_get_entry_data(&idata, resource->host, 
strlen(resource->host), internal_file, strlen(internal_file), "r", 0, &error, 1 
TSRMLS_CC)) {
                /* constraints of fp refcount were not met */
                if (error) {
                        php_stream_wrapper_log_error(wrapper, options 
TSRMLS_CC, "unlink of \"%s\" failed: %s", url, error);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/util.c?r1=1.57&r2=1.58&diff_format=u
Index: php-src/ext/phar/util.c
diff -u php-src/ext/phar/util.c:1.57 php-src/ext/phar/util.c:1.58
--- php-src/ext/phar/util.c:1.57        Wed May 14 21:27:31 2008
+++ php-src/ext/phar/util.c     Thu May 15 16:09:21 2008
@@ -18,7 +18,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: util.c,v 1.57 2008/05/14 21:27:31 sfox Exp $ */
+/* $Id: util.c,v 1.58 2008/05/15 16:09:21 cellog Exp $ */
 
 #include "phar_internal.h"
 #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
@@ -146,6 +146,11 @@
                return FAILURE;
        }
 
+       if (path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", 
sizeof(".phar")-1)) {
+               /* no creating magic phar files by mounting them */
+               return FAILURE;
+       }
+
        is_phar = (filename_len > 7 && !memcmp(filename, "phar://", 7));
 
        entry.phar = phar;
@@ -483,7 +488,7 @@
  * appended, truncated, or read.  For read, if the entry is marked unmodified, 
it is
  * assumed that the file pointer, if present, is opened for reading
  */
-int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error TSRMLS_DC) 
/* {{{ */
+int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error, int 
security TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
        phar_entry_info *entry;
@@ -515,14 +520,14 @@
                return FAILURE;
        }
        if (allow_dir) {
-               if ((entry = phar_get_entry_info_dir(phar, path, path_len, 
allow_dir, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error 
TSRMLS_CC)) == NULL) {
+               if ((entry = phar_get_entry_info_dir(phar, path, path_len, 
allow_dir, for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, 
security TSRMLS_CC)) == NULL) {
                        if (for_create && (!PHAR_G(readonly) || phar->is_data)) 
{
                                return SUCCESS;
                        }
                        return FAILURE;
                }
        } else {
-               if ((entry = phar_get_entry_info(phar, path, path_len, 
for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error TSRMLS_CC)) == 
NULL) {
+               if ((entry = phar_get_entry_info(phar, path, path_len, 
for_create && !PHAR_G(readonly) && !phar->is_data ? NULL : error, security 
TSRMLS_CC)) == NULL) {
                        if (for_create && (!PHAR_G(readonly) || phar->is_data)) 
{
                                return SUCCESS;
                        }
@@ -608,7 +613,7 @@
 /**
  * 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, char allow_dir, char **error TSRMLS_DC) 
/* {{{ */
+phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, 
char *path, int path_len, char *mode, char allow_dir, char **error, int 
security TSRMLS_DC) /* {{{ */
 {
        phar_archive_data *phar;
        phar_entry_info *entry, etemp;
@@ -626,7 +631,7 @@
                return NULL;
        }
 
-       if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, 
path_len, mode, allow_dir, error TSRMLS_CC)) {
+       if (FAILURE == phar_get_entry_data(&ret, fname, fname_len, path, 
path_len, mode, allow_dir, error, security TSRMLS_CC)) {
                return NULL;
        } else if (ret) {
                return ret;
@@ -1118,9 +1123,9 @@
 /**
  * retrieve information on a file contained within a phar, or null if it ain't 
there
  */
-phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int 
path_len, char **error TSRMLS_DC) /* {{{ */
+phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int 
path_len, char **error, int security TSRMLS_DC) /* {{{ */
 {
-       return phar_get_entry_info_dir(phar, path, path_len, 0, error 
TSRMLS_CC);
+       return phar_get_entry_info_dir(phar, path, path_len, 0, error, security 
TSRMLS_CC);
 }
 /* }}} */
 /**
@@ -1128,7 +1133,7 @@
  * allow_dir is 0 for none, 1 for both empty directories in the phar and temp 
directories, and 2 for only
  * valid pre-existing empty directory entries
  */
-phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, 
int path_len, char dir, char **error TSRMLS_DC) /* {{{ */
+phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, 
int path_len, char dir, char **error, int security TSRMLS_DC) /* {{{ */
 {
        const char *pcr_error;
        phar_entry_info *entry;
@@ -1144,6 +1149,12 @@
                *error = NULL;
        }
 
+       if (security && path_len >= sizeof(".phar")-1 && !memcmp(path, ".phar", 
sizeof(".phar")-1)) {
+               if (error) {
+                       spprintf(error, 4096, "phar error: cannot directly 
access magic \".phar\" directory or files within it");
+               }
+               return NULL;
+       }
        if (!path_len && !dir) {
                if (error) {
                        spprintf(error, 4096, "phar error: invalid path \"%s\" 
must not be empty", path);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/phar_extract2.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/phar_extract2.phpt
diff -u /dev/null php-src/ext/phar/tests/phar_extract2.phpt:1.2
--- /dev/null   Thu May 15 16:09:21 2008
+++ php-src/ext/phar/tests/phar_extract2.phpt   Thu May 15 16:09:21 2008
@@ -0,0 +1,60 @@
+--TEST--
+Phar: Phar::extractTo() - .phar safety
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--INI--
+phar.readonly=0
+--FILE--
+<?php
+
+$fname = dirname(__FILE__) . '/tempmanifest2.phar.php';
+$pname = 'phar://' . $fname;
+
+$phar = new Phar($fname);
+$phar->setDefaultStub();
+$phar->setAlias('fred');
+$phar['file1.txt'] = 'hi';
+$phar['file2.txt'] = 'hi2';
+$phar['subdir/ectory/file.txt'] = 'hi3';
+$phar->mount($pname . '/mount', __FILE__);
+$phar->addEmptyDir('one/level');
+
+$phar->extractTo(dirname(__FILE__) . '/extract', 'mount');
+$phar->extractTo(dirname(__FILE__) . '/extract');
+$out = array();
+
+foreach (new RecursiveIteratorIterator(new 
RecursiveDirectoryIterator(dirname(__FILE__) . '/extract'), 
RecursiveIteratorIterator::CHILD_FIRST) as $path => $file) {
+       $extracted[] = $path;
+}
+
+sort($extracted);
+
+foreach ($extracted as $out) {
+       echo "$out\n";
+}
+
+?>
+===DONE===
+--CLEAN--
+<?php
[EMAIL PROTECTED](dirname(__FILE__) . '/tempmanifest2.phar.php');
+$dir = dirname(__FILE__) . '/extract/';
[EMAIL PROTECTED]($dir . 'file1.txt');
[EMAIL PROTECTED]($dir . 'file2.txt');
[EMAIL PROTECTED]($dir . 'subdir/ectory/file.txt');
[EMAIL PROTECTED]($dir . 'subdir/ectory');
[EMAIL PROTECTED]($dir . 'subdir');
[EMAIL PROTECTED]($dir . 'one/level');
[EMAIL PROTECTED]($dir . 'one');
[EMAIL PROTECTED]($dir);
+$dir = dirname(__FILE__) . '/extract1/';
[EMAIL PROTECTED]($dir);
+?>
+--EXPECTF--
+%sextract%cfile1.txt
+%sextract%cfile2.txt
+%sextract%cone
+%sextract%csubdir
+%sextract%csubdir%cectory
+%sextract%csubdir%cectory%cfile.txt
+===DONE===
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/phar_offset_check.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/phar/tests/phar_offset_check.phpt
diff -u /dev/null php-src/ext/phar/tests/phar_offset_check.phpt:1.2
--- /dev/null   Thu May 15 16:09:21 2008
+++ php-src/ext/phar/tests/phar_offset_check.phpt       Thu May 15 16:09:21 2008
@@ -0,0 +1,78 @@
+--TEST--
+Phar: disallow stub and alias setting via offset*() methods
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+<?php if (!extension_loaded("spl")) die("skip SPL not available"); ?>
+--INI--
+phar.readonly=0
+phar.require_hash=1
+--FILE--
+<?php
+
+$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php';
+$pname = 'phar://'.$fname;
+
+$phar = new Phar($fname);
+$phar->setDefaultStub();
+$phar->setAlias('susan');
+$phar['a.txt'] = "first file\n";
+$phar['b.txt'] = "second file\n";
+
+try {
+       $phar->offsetGet('.phar/stub.php');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+try {
+       $phar->offsetGet('.phar/alias.txt');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+try {
+       $phar->offsetSet('.phar/stub.php', '<?php __HALT_COMPILER(); ?>');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+var_dump(strlen($phar->getStub()));
+
+try {
+       $phar->offsetUnset('.phar/stub.php');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+var_dump(strlen($phar->getStub()));
+
+try {
+       $phar->offsetSet('.phar/alias.txt', 'dolly');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+var_dump($phar->getAlias());
+
+try {
+       $phar->offsetUnset('.phar/alias.txt');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+var_dump($phar->getAlias());
+
+?>
+===DONE===
+--CLEAN--
+<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . 
'.phar.php'); ?>
+--EXPECTF--
+Entry .phar/stub.php does not exist
+Entry .phar/alias.txt does not exist
+Cannot set stub ".phar/stub.php" directly in phar 
"%sphar_offset_check.phar.php", use setStub
+int(6661)
+int(6661)
+Cannot set alias ".phar/alias.txt" directly in phar 
"%sphar_offset_check.phar.php", use setAlias
+string(5) "susan"
+string(5) "susan"
+===DONE===
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/030.phpt?r1=1.6&r2=1.7&diff_format=u
Index: php-src/ext/phar/tests/030.phpt
diff -u php-src/ext/phar/tests/030.phpt:1.6 php-src/ext/phar/tests/030.phpt:1.7
--- php-src/ext/phar/tests/030.phpt:1.6 Wed Feb 20 13:11:38 2008
+++ php-src/ext/phar/tests/030.phpt     Thu May 15 16:09:21 2008
@@ -11,11 +11,12 @@
 $file = '<?php include "' . $pname . '/a.php"; __HALT_COMPILER(); ?>';
 
 $files = array();
-$files['a.php']   = '<?php echo "This is a\n"; include \''.$pname.'/b.php\'; 
?>';      
-$files['b.php']   = '<?php echo "This is b\n"; include \''.$pname.'/b/c.php\'; 
?>';    
-$files['b/c.php'] = '<?php echo "This is b/c\n"; include 
\''.$pname.'/b/d.php\'; ?>';  
-$files['b/d.php'] = '<?php echo "This is b/d\n"; include \''.$pname.'/e.php\'; 
?>';    
-$files['e.php']   = '<?php echo "This is e\n"; ?>';                            
      
+$files['a.php']   = '<?php echo "This is a\n"; include \''.$pname.'/b.php\'; 
?>';
+$files['b.php']   = '<?php echo "This is b\n"; include \''.$pname.'/b/c.php\'; 
?>';
+$files['b/c.php'] = '<?php echo "This is b/c\n"; include 
\''.$pname.'/b/d.php\'; ?>';
+$files['b/d.php'] = '<?php echo "This is b/d\n"; include \''.$pname.'/e.php\'; 
?>';
+$files['e.php']   = '<?php echo "This is e\n"; ?>';
+$files['.phar/test'] = '<?php bad boy ?>';
 
 include 'files/phar_test.inc';
 
@@ -23,6 +24,13 @@
 
 require $pname . '/a.php';
 
+$p = new Phar($fname);
+var_dump(isset($p['.phar/test']));
+try {
+$p['.phar/test'];
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
 ?>
 ===DONE===
 --CLEAN--
@@ -35,4 +43,6 @@
 This is b/c
 This is b/d
 This is e
+bool(false)
+Cannot directly get any files or directories in magic ".phar" directory
 ===DONE===
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/addfuncs.phpt?r1=1.2&r2=1.3&diff_format=u
Index: php-src/ext/phar/tests/addfuncs.phpt
diff -u php-src/ext/phar/tests/addfuncs.phpt:1.2 
php-src/ext/phar/tests/addfuncs.phpt:1.3
--- php-src/ext/phar/tests/addfuncs.phpt:1.2    Thu Apr 24 05:00:02 2008
+++ php-src/ext/phar/tests/addfuncs.phpt        Thu May 15 16:09:21 2008
@@ -28,6 +28,16 @@
 } catch (Exception $e) {
 echo $e->getMessage() . "\n";
 }
+try {
+$phar->addFile($pname . '/a', '.phar/stub.php');
+} catch (Exception $e) {
+echo $e->getMessage() . "\n";
+}
+try {
+$phar->addFromString('.phar/stub.php', 'hi');
+} catch (Exception $e) {
+echo $e->getMessage() . "\n";
+}
 ?>
 ===DONE===
 --CLEAN--
@@ -38,4 +48,6 @@
 Entry phar://%saddfuncs.phar.php/a does not exist and cannot be created: phar 
error: invalid path "phar://%saddfuncs.phar.php/a" contains double slash
 Entry a does not exist and cannot be created: phar error: file "a" in phar 
"%saddfuncs.phar.php" cannot be opened for writing, readable file pointers are 
open
 phar error: unable to open file "%s/does/not/exist" to add to phar archive
+Cannot create any files in magic ".phar" directory
+Cannot create any files in magic ".phar" directory
 ===DONE===
\ No newline at end of file
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/mkdir.phpt?r1=1.4&r2=1.5&diff_format=u
Index: php-src/ext/phar/tests/mkdir.phpt
diff -u php-src/ext/phar/tests/mkdir.phpt:1.4 
php-src/ext/phar/tests/mkdir.phpt:1.5
--- php-src/ext/phar/tests/mkdir.phpt:1.4       Mon May 12 00:43:10 2008
+++ php-src/ext/phar/tests/mkdir.phpt   Thu May 15 16:09:21 2008
@@ -19,6 +19,11 @@
 rmdir($pname . '/a');
 $a->addEmptyDir('bb');
 $a->addEmptyDir('bb');
+try {
+$a->addEmptyDir('.phar');
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
 ?>
 ===DONE===
 --CLEAN--
@@ -38,4 +43,5 @@
 Warning: rmdir(): phar error: cannot remove directory "" in phar "foo.phar", 
directory does not exist in %smkdir.php on line %d
 
 Warning: rmdir(): phar error: cannot remove directory "a" in phar 
"%smkdir.phar.php", phar error: path "a" exists and is a not a directory in 
%smkdir.php on line %d
+Cannot create a directory in magic ".phar" directory
 ===DONE===
\ No newline at end of file
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/mounteddir.phpt?r1=1.5&r2=1.6&diff_format=u
Index: php-src/ext/phar/tests/mounteddir.phpt
diff -u php-src/ext/phar/tests/mounteddir.phpt:1.5 
php-src/ext/phar/tests/mounteddir.phpt:1.6
--- php-src/ext/phar/tests/mounteddir.phpt:1.5  Sat Apr 26 05:28:55 2008
+++ php-src/ext/phar/tests/mounteddir.phpt      Thu May 15 16:09:21 2008
@@ -17,6 +17,11 @@
 echo file_get_contents(Phar::running(1) . "/testit/existing.txt"), "\n";
 include "testit/extfile.php";
 include "testit/extfile2.php";
+try {
+Phar::mount(".phar/stub.php", dirname(Phar::running(0)) . 
"/testit/extfile.php");
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
 ?>';
 $a['testit/existing.txt'] = 'oops';
 $a->setStub('<?php
@@ -94,6 +99,7 @@
 oops
 string(%d) "phar://%sextfile.php"
 string(%d) "phar://%sextfile2.php"
+Mounting of .phar/stub.php to %sextfile.php within phar 
%stests/tempmanifest1.phar.php failed
 .
 ..
 directory
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/phar_buildfromiterator4.phpt?r1=1.4&r2=1.5&diff_format=u
Index: php-src/ext/phar/tests/phar_buildfromiterator4.phpt
diff -u php-src/ext/phar/tests/phar_buildfromiterator4.phpt:1.4 
php-src/ext/phar/tests/phar_buildfromiterator4.phpt:1.5
--- php-src/ext/phar/tests/phar_buildfromiterator4.phpt:1.4     Fri Jan  4 
16:26:43 2008
+++ php-src/ext/phar/tests/phar_buildfromiterator4.phpt Thu May 15 16:09:21 2008
@@ -38,7 +38,14 @@
 try {
        chdir(dirname(__FILE__));
        $phar = new Phar(dirname(__FILE__) . '/buildfromiterator.phar');
-       var_dump($phar->buildFromIterator(new myIterator(array('a' => 
basename(__FILE__, 'php') . 'phpt'))));
+       var_dump($phar->buildFromIterator(new myIterator(
+               array(
+                       'a' => basename(__FILE__, 'php') . 'phpt',
+                       // demonstrate that none of these are added
+                       '.phar/stub.php' => basename(__FILE__, 'php') . 'phpt',
+                       '.phar/alias.txt' => basename(__FILE__, 'php') . 'phpt',
+                       '.phar/oops' => basename(__FILE__, 'php') . 'phpt',
+               ))));
 } catch (Exception $e) {
        var_dump(get_class($e));
        echo $e->getMessage() . "\n";
@@ -57,6 +64,18 @@
 key
 next
 valid
+current
+key
+next
+valid
+current
+key
+next
+valid
+current
+key
+next
+valid
 array(1) {
   ["a"]=>
   string(%d) "%sphar_buildfromiterator4.phpt"
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/phar_copy.phpt?r1=1.6&r2=1.7&diff_format=u
Index: php-src/ext/phar/tests/phar_copy.phpt
diff -u php-src/ext/phar/tests/phar_copy.phpt:1.6 
php-src/ext/phar/tests/phar_copy.phpt:1.7
--- php-src/ext/phar/tests/phar_copy.phpt:1.6   Thu Apr 24 04:14:04 2008
+++ php-src/ext/phar/tests/phar_copy.phpt       Thu May 15 16:09:21 2008
@@ -57,6 +57,16 @@
 $p2['a']->compress(Phar::GZ);
 $p2->copy('a', 'd');
 echo $p2['d']->getContent() . "\n";
+try {
+$p2->copy('d', '.phar/stub.php');
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
+try {
+$p2->copy('.phar/stub.php', 'd');
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
 ?>
 ===DONE===
 --CLEAN--
@@ -69,4 +79,6 @@
 file "notexisting" cannot be copied to file "another", file does not exist in 
%sphar_copy2.phar.php
 file "a" cannot be copied to file "b", file must not already exist in phar 
%sphar_copy2.phar.php
 hi
+file "d" cannot be copied to file ".phar/stub.php", cannot copy to Phar 
meta-file in %sphar_copy2.phar.php
+file ".phar/stub.php" cannot be copied to file "d", cannot copy Phar meta-file 
in %sphar_copy2.phar.php
 ===DONE===
\ No newline at end of file
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/phar_offset_get_error.phpt?r1=1.4&r2=1.5&diff_format=u
Index: php-src/ext/phar/tests/phar_offset_get_error.phpt
diff -u php-src/ext/phar/tests/phar_offset_get_error.phpt:1.4 
php-src/ext/phar/tests/phar_offset_get_error.phpt:1.5
--- php-src/ext/phar/tests/phar_offset_get_error.phpt:1.4       Wed Jan  9 
00:58:36 2008
+++ php-src/ext/phar/tests/phar_offset_get_error.phpt   Thu May 15 16:09:21 2008
@@ -27,6 +27,18 @@
 }
 
 include($pname . $iname);
+
+// extra coverage
+try {
+$p['.phar/oops'] = 'hi';
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
+try {
+$a = $p['.phar/stub.php'];
+} catch (Exception $e) {
+echo $e->getMessage(),"\n";
+}
 ?>
 ===DONE===
 --CLEAN--
@@ -34,4 +46,6 @@
 --EXPECT--
 Entry /error/.. does not exist and cannot be created: phar error: invalid path 
"/error/.." contains upper directory reference
 foobar
+Cannot set any files or directories in magic ".phar" directory
+Entry .phar/stub.php does not exist
 ===DONE===
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/zf_test.phpt?r1=1.11&r2=1.12&diff_format=u
Index: php-src/ext/phar/tests/zf_test.phpt
diff -u php-src/ext/phar/tests/zf_test.phpt:1.11 
php-src/ext/phar/tests/zf_test.phpt:1.12
--- php-src/ext/phar/tests/zf_test.phpt:1.11    Tue May 13 14:49:36 2008
+++ php-src/ext/phar/tests/zf_test.phpt Thu May 15 16:09:21 2008
@@ -40,7 +40,6 @@
 unlink(dirname(__FILE__) . '/zfapp.phar.tar.gz');
 ?>
 --EXPECTF--
-phar://%szfapp.phar.tar.gz/.phar/stub.php
 phar://%szfapp.phar.tar.gz/application/default/controllers/ErrorController.php
 phar://%szfapp.phar.tar.gz/application/default/controllers/IndexController.php
 phar://%szfapp.phar.tar.gz/application/default/views/scripts/error/error.phtml
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/tar/dir.phpt?r1=1.3&r2=1.4&diff_format=u
Index: php-src/ext/phar/tests/tar/dir.phpt
diff -u php-src/ext/phar/tests/tar/dir.phpt:1.3 
php-src/ext/phar/tests/tar/dir.phpt:1.4
--- php-src/ext/phar/tests/tar/dir.phpt:1.3     Fri May  2 05:05:54 2008
+++ php-src/ext/phar/tests/tar/dir.phpt Thu May 15 16:09:21 2008
@@ -17,6 +17,7 @@
 var_dump($phar->isFileFormat(Phar::TAR));
 
 $phar->addEmptyDir('test');
+var_dump(isset($phar['.phar/stub.php']));
 var_dump($phar['test']->isDir());
 var_dump($phar['test/']->isDir());
 copy($fname, $fname2);
@@ -35,6 +36,7 @@
 <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . 
'.2.phar.php'); ?>
 --EXPECT--
 bool(true)
+bool(false)
 bool(true)
 bool(true)
 bool(true)
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/tar/tar_003.phpt?r1=1.5&r2=1.6&diff_format=u
Index: php-src/ext/phar/tests/tar/tar_003.phpt
diff -u php-src/ext/phar/tests/tar/tar_003.phpt:1.5 
php-src/ext/phar/tests/tar/tar_003.phpt:1.6
--- php-src/ext/phar/tests/tar/tar_003.phpt:1.5 Mon Mar  3 08:41:14 2008
+++ php-src/ext/phar/tests/tar/tar_003.phpt     Thu May 15 16:09:21 2008
@@ -55,8 +55,6 @@
 --EXPECT--
 hi there!
 dir
-.phar
-dir
 dir
 dir
 internal
@@ -64,8 +62,6 @@
 tar_003.phpt
 second round
 dir
-.phar
-dir
 dir
 dir
 internal

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to