diff options
author | Greg Beaver <cellog@php.net> | 2008-05-11 19:17:51 +0000 |
---|---|---|
committer | Greg Beaver <cellog@php.net> | 2008-05-11 19:17:51 +0000 |
commit | 38d5943ee6e31f921fe40d7f0049cb14e8222b27 (patch) | |
tree | 6c5ec5fa4edd3435fd0d6a27a8af01304d2467b5 | |
parent | 5ddb49caec245fd9e055d348350198e0e57592a0 (diff) | |
download | php-git-38d5943ee6e31f921fe40d7f0049cb14e8222b27.tar.gz |
increase code coverage of funcinterceptors to 90%+, fix many bugs, fix errant wrong test condition in fgc_edgecases
-rw-r--r-- | ext/phar/func_interceptors.c | 176 | ||||
-rw-r--r-- | ext/phar/phar.c | 2 | ||||
-rwxr-xr-x | ext/phar/phar_object.c | 3 | ||||
-rw-r--r-- | ext/phar/tests/fgc_edgecases.phpt | 94 | ||||
-rw-r--r-- | ext/phar/tests/fopen_edgecases.phpt | 7 | ||||
-rw-r--r-- | ext/phar/tests/fopen_edgecases2.phpt | 43 | ||||
-rw-r--r-- | ext/phar/tests/opendir_edgecases.phpt | 46 | ||||
-rw-r--r-- | ext/phar/tests/phar_buildfromdirectory4.phpt | 4 | ||||
-rw-r--r-- | ext/phar/tests/phar_buildfromdirectory5.phpt | 4 | ||||
-rw-r--r-- | ext/phar/tests/readfile_edgecases.phpt | 62 | ||||
-rw-r--r-- | ext/phar/tests/stat.phpt | 2 | ||||
-rw-r--r-- | ext/phar/tests/stat2.phpt | 59 | ||||
-rw-r--r-- | ext/phar/util.c | 11 |
13 files changed, 445 insertions, 68 deletions
diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index db28631638..250ca0556b 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -54,15 +54,14 @@ PHAR_FUNC(phar_opendir) /* {{{ */ entry = estrndup(filename, filename_len); /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */ entry_len = filename_len; - if (strstr(entry, "://")) { - efree(arch); - efree(entry); - goto skip_phar; - } /* retrieving a file within the current directory, so use this if possible */ entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC); - spprintf(&name, 4096, "phar://%s/%s", arch, entry); + if (entry[0] == '/') { + spprintf(&name, 4096, "phar://%s%s", arch, entry); + } else { + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + } efree(entry); efree(arch); if (zcontext) { @@ -71,7 +70,7 @@ PHAR_FUNC(phar_opendir) /* {{{ */ stream = php_stream_opendir(name, REPORT_ERRORS, context); efree(name); if (!stream) { - goto skip_phar; + RETURN_FALSE; } php_stream_to_zval(stream, return_value); return; @@ -111,17 +110,16 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */ } fname_len = strlen(fname); if (SUCCESS == phar_split_fname(fname, fname_len, &arch, &arch_len, &entry, &entry_len, 2, 0 TSRMLS_CC)) { - char *name, *old; + char *name; phar_archive_data **pphar; - old = entry; + efree(entry); entry = filename; /* fopen within phar, if :// is not in the url, then prepend phar://<archive>/ */ entry_len = filename_len; if (ZEND_NUM_ARGS() == 5 && maxlen < 0) { efree(arch); - efree(old); php_error_docref(NULL TSRMLS_CC, E_WARNING, "length must be greater than or equal to zero"); RETURN_FALSE; } @@ -129,36 +127,45 @@ PHAR_FUNC(phar_file_get_contents) /* {{{ */ /* retrieving a file defaults to within the current directory, so use this if possible */ if (FAILURE == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { efree(arch); - efree(old); goto skip_phar; } if (use_include_path) { if ((entry = phar_find_in_include_path(entry, entry_len, NULL TSRMLS_CC))) { name = entry; + goto phar_it; } else { /* this file is not in the phar, use the original path */ efree(arch); - efree(old); goto skip_phar; } } else { entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); - if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { - /* this file is not in the phar, use the original path */ - efree(arch); - efree(old); - efree(entry); - goto skip_phar; + if (entry[0] == '/') { + if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { + /* this file is not in the phar, use the original path */ +notfound: + efree(arch); + efree(entry); + goto skip_phar; + } + } else { + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + goto notfound; + } } /* auto-convert to phar:// */ - spprintf(&name, 4096, "phar://%s%s", arch, entry); + if (entry[0] == '/') { + spprintf(&name, 4096, "phar://%s%s", arch, entry); + } else { + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + } if (entry != filename) { efree(entry); } } +phar_it: efree(arch); - efree(old); if (zcontext) { context = php_stream_context_from_zval(zcontext, 0); } @@ -247,14 +254,25 @@ PHAR_FUNC(phar_readfile) /* {{{ */ } } else { entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); - if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { - /* this file is not in the phar, use the original path */ - efree(entry); - efree(arch); - goto skip_phar; + if (entry[0] == '/') { + if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { + /* this file is not in the phar, use the original path */ +notfound: + efree(entry); + efree(arch); + goto skip_phar; + } + } else { + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + goto notfound; + } } /* auto-convert to phar:// */ - spprintf(&name, 4096, "phar://%s%s", arch, entry); + if (entry[0] == '/') { + spprintf(&name, 4096, "phar://%s%s", arch, entry); + } else { + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + } efree(entry); } @@ -327,14 +345,26 @@ PHAR_FUNC(phar_fopen) /* {{{ */ } } else { entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); - if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { - /* this file is not in the phar, use the original path */ - efree(entry); - efree(arch); - goto skip_phar; + if (entry[0] == '/') { + if (!zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { + /* this file is not in the phar, use the original path */ +notfound: + efree(entry); + efree(arch); + goto skip_phar; + } + } else { + if (!zend_hash_exists(&((*pphar)->manifest), entry, entry_len)) { + /* this file is not in the phar, use the original path */ + goto notfound; + } } /* auto-convert to phar:// */ - spprintf(&name, 4096, "phar://%s%s", arch, entry); + if (entry[0] == '/') { + spprintf(&name, 4096, "phar://%s%s", arch, entry); + } else { + spprintf(&name, 4096, "phar://%s/%s", arch, entry); + } efree(entry); } @@ -452,14 +482,8 @@ void phar_fancy_stat(struct stat *stat_sb, int type, zval *return_value TSRMLS_D RETURN_STRING("link", 1); } switch(stat_sb->st_mode & S_IFMT) { - case S_IFIFO: RETURN_STRING("fifo", 1); - case S_IFCHR: RETURN_STRING("char", 1); case S_IFDIR: RETURN_STRING("dir", 1); - case S_IFBLK: RETURN_STRING("block", 1); case S_IFREG: RETURN_STRING("file", 1); -#if defined(S_IFSOCK) && !defined(ZEND_WIN32)&&!defined(__BEOS__) - case S_IFSOCK: RETURN_STRING("socket", 1); -#endif } php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown file type (%d)", stat_sb->st_mode&S_IFMT); RETURN_STRING("unknown", 1); @@ -586,13 +610,27 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type goto skip_phar; } entry = phar_fix_filepath(entry, &entry_len, 1 TSRMLS_CC); + if (entry[0] == '/') { + if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &data)) { + efree(entry); + goto stat_entry; + } + goto notfound; + } if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &data)) { efree(entry); goto stat_entry; } else { - char *save = PHAR_G(cwd), *save2 = entry; - int save_len = PHAR_G(cwd_len), save2_len = entry_len; - + char *save, *save2, *actual; + int save_len, save2_len, actual_len; + +notfound: + save = PHAR_G(cwd); + save2 = entry; + actual = entry[0] == '/' ? (entry + 1) : entry; + save_len = PHAR_G(cwd_len); + save2_len = entry_len; + actual_len = entry[0] == '/' ? (entry_len - 1) : entry_len; /* this file is not in the current directory, use the original path */ entry = estrndup(filename, filename_length); PHAR_G(cwd) = "/"; @@ -611,19 +649,19 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type uint keylen; ulong unused; + PHAR_G(cwd) = save; + PHAR_G(cwd_len) = save_len; /* original not found either, this is possibly a directory relative to cwd */ zend_hash_internal_pointer_reset(&phar->manifest); while (FAILURE != zend_hash_has_more_elements(&phar->manifest)) { if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - if (!memcmp(save2, key, save2_len)) { - PHAR_G(cwd) = save; - PHAR_G(cwd_len) = save_len; + if (!memcmp(actual, key, actual_len)) { efree(save2); efree(entry); /* directory found, all dirs have the same stat */ - if (key[save2_len] == '/') { + if (key[actual_len] == '/') { sb.st_size = 0; sb.st_mode = 0777; sb.st_mode |= S_IFDIR; /* regular directory */ @@ -645,10 +683,9 @@ void phar_file_stat(const char *filename, php_stat_len filename_length, int type } } } - PHAR_G(cwd) = save; - PHAR_G(cwd_len) = save_len; efree(entry); efree(save2); + efree(arch); /* Error Occured */ if (!IS_EXISTS_CHECK(type)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%sstat failed for %s", IS_LINK_OPERATION(type) ? "L" : "", filename); @@ -659,7 +696,11 @@ stat_entry: if (!data->is_dir) { sb.st_size = data->uncompressed_filesize; sb.st_mode = data->flags & PHAR_ENT_PERM_MASK; - sb.st_mode |= S_IFREG; /* regular file */ + if (data->link) { + sb.st_mode |= S_IFREG|S_IFLNK; /* regular file */ + } else { + sb.st_mode |= S_IFREG; /* regular file */ + } /* timestamp is just the timestamp when this was added to the phar */ #ifdef NETWARE sb.st_mtime.tv_sec = data->timestamp; @@ -674,6 +715,9 @@ stat_entry: sb.st_size = 0; sb.st_mode = data->flags & PHAR_ENT_PERM_MASK; sb.st_mode |= S_IFDIR; /* regular directory */ + if (data->link) { + sb.st_mode |= S_IFLNK; + } /* timestamp is just the timestamp when this was added to the phar */ #ifdef NETWARE sb.st_mtime.tv_sec = data->timestamp; @@ -837,12 +881,21 @@ PHAR_FUNC(phar_is_file) /* {{{ */ entry_len = filename_len; /* retrieving a file within the current directory, so use this if possible */ if (SUCCESS == (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { + phar_entry_info *etemp; + entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); - if (zend_hash_exists(&((*pphar)->manifest), entry + 1, entry_len - 1)) { - /* this file is not in the current directory, use the original path */ - efree(entry); - efree(arch); - RETURN_TRUE; + if (entry[0] == '/') { + if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) { + /* this file is not in the current directory, use the original path */ +found_it: + efree(entry); + efree(arch); + RETURN_BOOL(!etemp->is_dir); + } + } else { + if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) { + goto found_it; + } } } efree(entry); @@ -888,11 +941,18 @@ PHAR_FUNC(phar_is_link) /* {{{ */ phar_entry_info *etemp; entry = phar_fix_filepath(estrndup(entry, entry_len), &entry_len, 1 TSRMLS_CC); - if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) { - /* this file is not in the current directory, use the original path */ - efree(entry); - efree(arch); - RETURN_BOOL(etemp->link); + if (entry[0] == '/') { + if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry + 1, entry_len - 1, (void **) &etemp)) { + /* this file is not in the current directory, use the original path */ +found_it: + efree(entry); + efree(arch); + RETURN_BOOL(etemp->link); + } + } else { + if (SUCCESS == zend_hash_find(&((*pphar)->manifest), entry, entry_len, (void **) &etemp)) { + goto found_it; + } } } efree(entry); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index e1cbb5f1da..16b5288f47 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1702,7 +1702,7 @@ char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC) /* {{{ int ptr_length, new_phar_len = 1, path_length = *new_len; if (PHAR_G(cwd_len) && use_cwd && path_length > 2 && path[0] == '.' && path[1] == '/') { - free_path = path = estrndup(path, path_length); + free_path = path; new_phar_len = PHAR_G(cwd_len); new_phar = estrndup(PHAR_G(cwd), new_phar_len); } else { diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 1135df5760..08fd94d9ea 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -1943,6 +1943,9 @@ static zval *phar_convert_to_other(phar_archive_data *source, int convert, char return NULL; } newentry = *entry; + if (newentry.link) { + newentry.link = estrdup(newentry.link); + } if (FAILURE == phar_copy_file_contents(&newentry, phar->fp TSRMLS_CC)) { zend_hash_destroy(&(phar->manifest)); php_stream_close(phar->fp); diff --git a/ext/phar/tests/fgc_edgecases.phpt b/ext/phar/tests/fgc_edgecases.phpt new file mode 100644 index 0000000000..c440ea4afa --- /dev/null +++ b/ext/phar/tests/fgc_edgecases.phpt @@ -0,0 +1,94 @@ +--TEST-- +Phar: test edge cases of file_get_contents() function interception +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip");?> +--INI-- +phar.readonly=0 +--FILE-- +<?php +Phar::interceptFileFuncs(); +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$pname = 'phar://' . $fname; + +file_get_contents(array()); +chdir(dirname(__FILE__)); +file_put_contents($fname, "blah\n"); +file_put_contents("foob", "test\n"); +echo file_get_contents($fname); +unlink($fname); +mkdir($pname . '/oops'); +file_put_contents($pname . '/foo/hi', '<?php +echo file_get_contents("foo/" . basename(__FILE__)); +$context = stream_context_create(); +file_get_contents("./hi", 0, $context, 0, -1); +echo file_get_contents("foob"); +set_include_path("' . addslashes(dirname(__FILE__)) . '"); +echo file_get_contents("foob", true); +echo file_get_contents("./hi", 0, $context); +echo file_get_contents("../oops"); +echo file_get_contents("./hi", 0, $context, 50000); +ini_set("magic_quotes_runtime", 1); +echo file_get_contents("./hi"); +echo file_get_contents("./hi", 0, $context, 0, 0); +?> +'); +include $pname . '/foo/hi'; +?> +===DONE=== +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> +<?php rmdir(dirname(__FILE__) . '/poo'); ?> +<?php unlink(dirname(__FILE__) . '/foob'); ?> +--EXPECTF-- +blah +<?php +echo file_get_contents("foo/" . basename(__FILE__)); +$context = stream_context_create(); +file_get_contents("./hi", 0, $context, 0, -1); +echo file_get_contents("foob"); +set_include_path("/home/cellog/workspace/php5/ext/phar/tests"); +echo file_get_contents("foob", true); +echo file_get_contents("./hi", 0, $context); +echo file_get_contents("../oops"); +echo file_get_contents("./hi", 0, $context, 50000); +ini_set("magic_quotes_runtime", 1); +echo file_get_contents("./hi"); +echo file_get_contents("./hi", 0, $context, 0, 0); +?> + +Warning: file_get_contents(): length must be greater than or equal to zero in phar://%sfgc_edgecases.phar.php/foo/hi on line %d +test +test +<?php +echo file_get_contents("foo/" . basename(__FILE__)); +$context = stream_context_create(); +file_get_contents("./hi", 0, $context, 0, -1); +echo file_get_contents("foob"); +set_include_path("/home/cellog/workspace/php5/ext/phar/tests"); +echo file_get_contents("foob", true); +echo file_get_contents("./hi", 0, $context); +echo file_get_contents("../oops"); +echo file_get_contents("./hi", 0, $context, 50000); +ini_set("magic_quotes_runtime", 1); +echo file_get_contents("./hi"); +echo file_get_contents("./hi", 0, $context, 0, 0); +?> + +Warning: file_get_contents(phar://%sfgc_edgecases.phar.php/oops): failed to open stream: phar error: path "oops" is a directory in phar://%sfgc_edgecases.phar.php/foo/hi on line %d + +Warning: file_get_contents(): Failed to seek to position 50000 in the stream in phar://%sfgc_edgecases.phar.php/foo/hi on line %d +<?php +echo file_get_contents(\"foo/\" . basename(__FILE__)); +$context = stream_context_create(); +file_get_contents(\"./hi\", 0, $context, 0, -1); +echo file_get_contents(\"foob\"); +set_include_path(\"/home/cellog/workspace/php5/ext/phar/tests\"); +echo file_get_contents(\"foob\", true); +echo file_get_contents(\"./hi\", 0, $context); +echo file_get_contents(\"../oops\"); +echo file_get_contents(\"./hi\", 0, $context, 50000); +ini_set(\"magic_quotes_runtime\", 1); +echo file_get_contents(\"./hi\"); +echo file_get_contents(\"./hi\", 0, $context, 0, 0); +?> +===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/fopen_edgecases.phpt b/ext/phar/tests/fopen_edgecases.phpt index 209fc482a0..4c28ff31a1 100644 --- a/ext/phar/tests/fopen_edgecases.phpt +++ b/ext/phar/tests/fopen_edgecases.phpt @@ -59,6 +59,11 @@ rename($pname . '/hi', 'phar://foo.phar/hi'); ini_set('phar.readonly', 1); rename($pname . '/hi', $pname . '/there'); ini_set('phar.readonly', 0); +Phar::unlinkArchive($fname); +file_put_contents($pname . '/test.php', '<?php +$a = fopen("./notfound.php", "r"); +?>'); +include $pname . '/test.php'; ?> ===DONE=== @@ -114,4 +119,6 @@ Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/ Warning: rename(): phar error: cannot rename "phar://%sfopen_edgecases.phar.php/hi" to "phar://%sfopen_edgecases.phar.php/there": invalid or non-writable url "phar://%sfopen_edgecases.phar.php/hi" in %sfopen_edgecases.php on line %d +Warning: fopen(./notfound.php): failed to open stream: No such file or directory in phar://%sfopen_edgecases.phar.php/test.php on line %d + ===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/fopen_edgecases2.phpt b/ext/phar/tests/fopen_edgecases2.phpt new file mode 100644 index 0000000000..3579a2c221 --- /dev/null +++ b/ext/phar/tests/fopen_edgecases2.phpt @@ -0,0 +1,43 @@ +--TEST-- +Phar: test edge cases of fopen() function interception #2 +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip");?> +--INI-- +phar.readonly=0 +--FILE-- +<?php +Phar::interceptFileFuncs(); +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$pname = 'phar://' . $fname; + +fopen(array(), 'r'); +chdir(dirname(__FILE__)); +file_put_contents($fname, "blah\n"); +file_put_contents("foob", "test\n"); +$a = fopen($fname, 'rb'); +echo fread($a, 1000); +fclose($a); +unlink($fname); +mkdir($pname . '/oops'); +file_put_contents($pname . '/foo/hi', '<?php +$context = stream_context_create(); +$a = fopen("foob", "rb", false, $context); +echo fread($a, 1000); +fclose($a); +fopen("../oops", "r"); +?> +'); +include $pname . '/foo/hi'; +?> +===DONE=== +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> +<?php rmdir(dirname(__FILE__) . '/poo'); ?> +<?php unlink(dirname(__FILE__) . '/foob'); ?> +--EXPECTF-- +Warning: fopen() expects parameter 1 to be string, array given in %sfopen_edgecases2.php on line %d +blah +test + +Warning: fopen(phar://%sfopen_edgecases2.phar.php/oops): failed to open stream: phar error: path "oops" is a directory in phar://%sfopen_edgecases2.phar.php/foo/hi on line %d +===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/opendir_edgecases.phpt b/ext/phar/tests/opendir_edgecases.phpt new file mode 100644 index 0000000000..9fb515f116 --- /dev/null +++ b/ext/phar/tests/opendir_edgecases.phpt @@ -0,0 +1,46 @@ +--TEST-- +Phar: test edge cases of opendir() function interception +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip");?> +--INI-- +phar.readonly=0 +--FILE-- +<?php +Phar::interceptFileFuncs(); +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$pname = 'phar://' . $fname; +opendir(array()); +mkdir(dirname(__FILE__) . '/poo'); +chdir(dirname(__FILE__)); +$a = opendir('poo'); +while (false !== ($b = readdir($a))) { +echo "$b\n"; +} +closedir($a); +file_put_contents($pname . '/foo', '<?php +$context = stream_context_create(); +$a = opendir(".", $context); +$res = array(); +while (false !== ($b = readdir($a))) { +$res[] = $b; +} +sort($res); +foreach ($res as $b) { +echo "$b\n"; +} +opendir("oops"); +?>'); +include $pname . '/foo'; +?> +===DONE=== +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> +<?php rmdir(dirname(__FILE__) . '/poo'); +--EXPECTF-- +Warning: opendir() expects parameter 1 to be string, array given in %sopendir_edgecases.php on line %d +. +.. +foo + +Warning: opendir(phar://%sopendir_edgecases.phar.php/oops): failed to open dir: No such file or directory in phar://%sopendir_edgecases.phar.php/foo on line %d +===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/phar_buildfromdirectory4.phpt b/ext/phar/tests/phar_buildfromdirectory4.phpt index 886cad82d6..cf11d62af6 100644 --- a/ext/phar/tests/phar_buildfromdirectory4.phpt +++ b/ext/phar/tests/phar_buildfromdirectory4.phpt @@ -15,7 +15,9 @@ foreach(range(1, 4) as $i) { try { $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); - var_dump($phar->buildFromDirectory(dirname(__FILE__) . '/testdir')); + $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir'); + asort($a); + var_dump($a); } catch (Exception $e) { var_dump(get_class($e)); echo $e->getMessage() . "\n"; diff --git a/ext/phar/tests/phar_buildfromdirectory5.phpt b/ext/phar/tests/phar_buildfromdirectory5.phpt index fbf3e9b533..51e5cec691 100644 --- a/ext/phar/tests/phar_buildfromdirectory5.phpt +++ b/ext/phar/tests/phar_buildfromdirectory5.phpt @@ -15,7 +15,9 @@ foreach(range(1, 4) as $i) { try { $phar = new Phar(dirname(__FILE__) . '/buildfromdirectory.phar'); - var_dump($phar->buildFromDirectory(dirname(__FILE__) . '/testdir', '/\.txt/')); + $a = $phar->buildFromDirectory(dirname(__FILE__) . '/testdir', '/\.txt/'); + asort($a); + var_dump($a); } catch (Exception $e) { var_dump(get_class($e)); echo $e->getMessage() . "\n"; diff --git a/ext/phar/tests/readfile_edgecases.phpt b/ext/phar/tests/readfile_edgecases.phpt new file mode 100644 index 0000000000..de1f5912df --- /dev/null +++ b/ext/phar/tests/readfile_edgecases.phpt @@ -0,0 +1,62 @@ +--TEST-- +Phar: test edge cases of readfile() function interception +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip");?> +--INI-- +phar.readonly=0 +--FILE-- +<?php +Phar::interceptFileFuncs(); +$fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$pname = 'phar://' . $fname; + +readfile(array()); +chdir(dirname(__FILE__)); +file_put_contents($fname, "blah\n"); +file_put_contents("foob", "test\n"); +readfile($fname); +unlink($fname); +mkdir($pname . '/oops'); +file_put_contents($pname . '/foo/hi', '<?php +readfile("foo/" . basename(__FILE__)); +$context = stream_context_create(); +readfile("foob"); +set_include_path("' . addslashes(dirname(__FILE__)) . '"); +readfile("foob", true); +readfile("./hi", 0, $context); +readfile("../oops"); +?> +'); +include $pname . '/foo/hi'; +?> +===DONE=== +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.php'); ?> +<?php rmdir(dirname(__FILE__) . '/poo'); ?> +<?php unlink(dirname(__FILE__) . '/foob'); ?> +--EXPECTF-- +Warning: readfile() expects parameter 1 to be string, array given in %sreadfile_edgecases.php on line %d +blah +<?php +readfile("foo/" . basename(__FILE__)); +$context = stream_context_create(); +readfile("foob"); +set_include_path("/home/cellog/workspace/php5/ext/phar/tests"); +readfile("foob", true); +readfile("./hi", 0, $context); +readfile("../oops"); +?> +test +test +<?php +readfile("foo/" . basename(__FILE__)); +$context = stream_context_create(); +readfile("foob"); +set_include_path("/home/cellog/workspace/php5/ext/phar/tests"); +readfile("foob", true); +readfile("./hi", 0, $context); +readfile("../oops"); +?> + +Warning: readfile(phar://%sreadfile_edgecases.phar.php/oops): failed to open stream: phar error: path "oops" is a directory in phar://%sreadfile_edgecases.phar.php/foo/hi on line %d +===DONE===
\ No newline at end of file diff --git a/ext/phar/tests/stat.phpt b/ext/phar/tests/stat.phpt index e450cc3b01..020fc24f86 100644 --- a/ext/phar/tests/stat.phpt +++ b/ext/phar/tests/stat.phpt @@ -11,6 +11,8 @@ Phar::interceptFileFuncs(); var_dump(stat("")); $fname = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.php'; +$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.tar'; +$fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar'; $a = new Phar($fname); $a['index.php'] = '<?php echo "stat\n"; diff --git a/ext/phar/tests/stat2.phpt b/ext/phar/tests/stat2.phpt new file mode 100644 index 0000000000..559a28d3f0 --- /dev/null +++ b/ext/phar/tests/stat2.phpt @@ -0,0 +1,59 @@ +--TEST-- +Phar: test stat function interceptions and is_file/is_link edge cases +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip");?> +--INI-- +phar.readonly=0 +--FILE-- +<?php +Phar::interceptFileFuncs(); +is_file(); +is_link(); +var_dump(is_file(__FILE__)); + +$fname2 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.tar'; +$fname3 = dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.phar.tar'; +copy(dirname(__FILE__) . '/tar/files/links.tar', $fname2); +$a = new PharData($fname2); +$b = $a->convertToExecutable(); +unset($a); +Phar::unlinkArchive($fname2); +$b['foo/stat.php'] = '<?php +echo "is_link\n"; +var_dump(is_link("./stat.php"),is_file("./stat.php"), is_link("./oops"), is_file("./oops")); +var_dump(is_link("testit/link"), filetype("testit/link"), filetype("testit"), is_file("testit/link")); +echo "not found\n"; +var_dump(is_link("notfound")); +echo "dir\n"; +var_dump(is_dir("./bar"), is_file("foo/bar/blah")); +?>'; +$b->addEmptyDir('foo/bar/blah'); +$b->setStub('<?php +include "phar://" . __FILE__ . "/foo/stat.php"; +__HALT_COMPILER();'); +include $fname3; +?> +===DONE=== +--CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.tar'); ?> +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.tar'); ?> +--EXPECTF-- +Warning: Wrong parameter count for is_file() in %sstat2.php on line %d + +Warning: Wrong parameter count for is_link() in %sstat2.php on line %d +bool(true) +is_link +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +string(4) "link" +string(3) "dir" +bool(true) +not found +bool(false) +dir +bool(true) +bool(false) +===DONE===
\ No newline at end of file diff --git a/ext/phar/util.c b/ext/phar/util.c index f36d9a031c..ddd51eb6fe 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -228,15 +228,14 @@ char *phar_find_in_include_path(char *filename, int filename_len, phar_archive_d if (SUCCESS != phar_split_fname(fname, strlen(fname), &arch, &arch_len, &entry, &entry_len, 1, 0 TSRMLS_CC)) { return phar_save_resolve_path(filename, filename_len TSRMLS_CC); } + efree(entry); if (*filename == '.') { int try_len; if (SUCCESS != (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { efree(arch); - efree(entry); return phar_save_resolve_path(filename, filename_len TSRMLS_CC); } - efree(entry); try_len = filename_len; test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC); if (*test == '/') { @@ -255,14 +254,13 @@ char *phar_find_in_include_path(char *filename, int filename_len, phar_archive_d } } } - efree(entry); spprintf(&path, MAXPATHLEN, "phar://%s/%s%c%s", arch, PHAR_G(cwd), DEFAULT_DIR_SEPARATOR, PG(include_path)); efree(arch); ret = php_resolve_path(filename, filename_len, path TSRMLS_CC); efree(path); if (ret && strlen(ret) > 8 && !strncmp(ret, "phar://", 7)) { - char *arch, *entry; - int arch_len, entry_len, ret_len; + char *arch; + int arch_len, ret_len; ret_len = strlen(ret); /* found phar:// */ @@ -297,16 +295,15 @@ char *phar_find_in_include_path(char *filename, int filename_len, phar_archive_d goto doit; } + efree(entry); if (*filename == '.') { phar_archive_data **pphar; int try_len; if (SUCCESS != (zend_hash_find(&(PHAR_GLOBALS->phar_fname_map), arch, arch_len, (void **) &pphar))) { efree(arch); - efree(entry); goto doit; } - efree(entry); try_len = filename_len; test = phar_fix_filepath(estrndup(filename, filename_len), &try_len, 1 TSRMLS_CC); if (*test == '/') { |