From f210205e708c23a49c1fe751645968fb6c06b789 Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sun, 4 Feb 2007 20:10:03 +0000 Subject: [PATCH] - PHP_VERSION_ID exists only in newer PHPs (5.1+) - Improve error checking --- ext/phar/phar.c | 47 ++++++++++++++--------- ext/phar/phar_internal.h | 4 +- ext/phar/phar_object.c | 10 ++--- ext/phar/phar_path_check.c | 31 +++++++-------- ext/phar/phar_path_check.re | 15 ++++---- ext/phar/tests/phar_offset_get_error.phpt | 37 ++++++++++++++++++ 6 files changed, 97 insertions(+), 47 deletions(-) create mode 100755 ext/phar/tests/phar_offset_get_error.phpt diff --git a/ext/phar/phar.c b/ext/phar/phar.c index ec248f9e6e..670891ea61 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -235,14 +235,22 @@ static int phar_get_archive(phar_archive_data **archive, char *fname, int fname_ /** * 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 TSRMLS_DC) /* {{{ */ +phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, char **error TSRMLS_DC) /* {{{ */ { + const char *pcr_error; phar_entry_info *entry; - if (path && *path == '/') { - path++; - path_len--; + if (error) { + *error = NULL; + } + + if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) { + if (error) { + spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); + } + return NULL; } + if (!&phar->manifest.arBuckets) { return NULL; } @@ -257,7 +265,7 @@ phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int pa } /* }}} */ -#if PHP_VERSION_ID < 50202 +#if defined(PHP_VERSION_ID) && PHP_VERSION_ID < 50202 typedef struct { char *data; size_t fpos; @@ -297,7 +305,7 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) { return FAILURE; } - if ((entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC)) == NULL) { + if ((entry = phar_get_entry_info(phar, path, path_len, for_create && !PHAR_G(readonly) ? NULL : error TSRMLS_CC)) == NULL) { if (for_create && !PHAR_G(readonly)) { return SUCCESS; } @@ -328,7 +336,9 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len if (entry->fp) { /* make a copy */ if (for_trunc) { -#if PHP_VERSION_ID < 50202 +#if PHP_VERSION_ID >= 50202 + php_stream_truncate_set_size(entry->fp, 0); +#else if (php_stream_is(entry->fp, PHP_STREAM_IS_TEMP)) { if (php_stream_is(*(php_stream**)entry->fp->abstract, PHP_STREAM_IS_MEMORY)) { php_stream *inner = *(php_stream**)entry->fp->abstract; @@ -355,8 +365,6 @@ static int phar_get_entry_data(phar_entry_data **ret, char *fname, int fname_len } return FAILURE; } -#else - php_stream_truncate_set_size(entry->fp, 0); #endif entry->is_modified = 1; phar->is_modified = 1; @@ -434,16 +442,8 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char phar_archive_data *phar; phar_entry_info *entry, etemp; phar_entry_data *ret; - phar_path_check_result res; const char *pcr_error; - if ((res = phar_path_check(path, &path_len, &pcr_error)) > pcr_is_ok) { - if (error) { - spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); - } - return NULL; - } - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, error TSRMLS_CC)) { return NULL; } @@ -454,6 +454,13 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char return ret; } + if (phar_path_check(&path, &path_len, &pcr_error) > pcr_is_ok) { + if (error) { + spprintf(error, 0, "phar error: invalid path \"%s\" contains %s", path, pcr_error); + } + return NULL; + } + /* create a new phar data holder */ ret = (phar_entry_data *) emalloc(sizeof(phar_entry_data)); @@ -471,7 +478,11 @@ phar_entry_data *phar_get_or_create_entry_data(char *fname, int fname_len, char etemp.phar = phar; zend_hash_add(&phar->manifest, etemp.filename, path_len, (void*)&etemp, sizeof(phar_entry_info), NULL); /* retrieve the phar manifest copy */ - entry = phar_get_entry_info(phar, path, path_len TSRMLS_CC); + entry = phar_get_entry_info(phar, path, path_len, error TSRMLS_CC); + + if (!entry) { + //return NULL; + } phar->refcount++; ret->phar = phar; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 8bbb4ee7f8..a172686f63 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -252,7 +252,7 @@ static int phar_dir_stat( php_stream *stream, php_stream_statbuf *ssb TSRMLS_ 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 TSRMLS_DC); +phar_entry_info *phar_get_entry_info(phar_archive_data *phar, char *path, int path_len, 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 **error TSRMLS_DC); int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **error TSRMLS_DC); int phar_split_fname(char *filename, int filename_len, char **arch, int *arch_len, char **entry, int *entry_len TSRMLS_DC); @@ -268,7 +268,7 @@ typedef enum { pcr_err_empty_entry } phar_path_check_result; -phar_path_check_result phar_path_check(const char *p, int *len, const char **error); +phar_path_check_result phar_path_check(char **p, int *len, const char **error); END_EXTERN_C() diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index f3c78d61da..21dd365389 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -520,7 +520,7 @@ PHP_METHOD(Phar, offsetExists) */ PHP_METHOD(Phar, offsetGet) { - char *fname; + char *fname, *error; int fname_len; zval *zfname; PHAR_ARCHIVE_OBJECT(); @@ -529,8 +529,8 @@ PHP_METHOD(Phar, offsetGet) return; } - if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len TSRMLS_CC)) { - zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist", fname); + if (!phar_get_entry_info(phar_obj->arc.archive, fname, fname_len, &error TSRMLS_CC)) { + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "Entry %s does not exist%s%s", fname, error?", ":"", error?error:""); } else { fname_len = spprintf(&fname, 0, "phar://%s/%s", phar_obj->arc.archive->fname, fname); MAKE_STD_ZVAL(zfname); @@ -769,10 +769,10 @@ PHP_METHOD(PharFileInfo, __construct) return; } - if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len TSRMLS_CC)) == NULL) { + if ((entry_info = phar_get_entry_info(phar_data, entry, entry_len, &error TSRMLS_CC)) == NULL) { efree(arch); zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, - "Cannot access phar file entry '%s' in archive '%s'", entry, arch); + "Cannot access phar file entry '%s' in archive '%s'%s%s", entry, arch, error?", ":"", error?error:""); efree(entry); return; } diff --git a/ext/phar/phar_path_check.c b/ext/phar/phar_path_check.c index fba3a5bd32..50c3a46e05 100755 --- a/ext/phar/phar_path_check.c +++ b/ext/phar/phar_path_check.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.11.0 on Sun Feb 4 11:21:09 2007 */ +/* Generated by re2c 0.11.0 on Sun Feb 4 14:40:54 2007 */ #line 1 "ext/phar/phar_path_check.re" /* +----------------------------------------------------------------------+ @@ -22,9 +22,9 @@ #include "phar_internal.h" -phar_path_check_result phar_path_check(const char *s, int *len, const char **error) +phar_path_check_result phar_path_check(char **s, int *len, const char **error) { - const unsigned char *p = (const unsigned char*)s; + const unsigned char *p = (const unsigned char*)*s; const unsigned char *m; #define YYCTYPE unsigned char #define YYCURSOR p @@ -69,7 +69,7 @@ yy3: if(yych <= '.') goto yy16; if(yych <= '/') goto yy17; yy4: -#line 77 "ext/phar/phar_path_check.re" +#line 78 "ext/phar/phar_path_check.re" { goto loop; } @@ -94,10 +94,10 @@ yy9: ++YYCURSOR; #line 62 "ext/phar/phar_path_check.re" { - if (*s == '/') { - s++; + if (**s == '/') { + (*s)++; } - *len = (p - (const unsigned char*)s) -1; + *len = (p - (const unsigned char*)*s) -1; *error = NULL; return pcr_use_query; } @@ -106,13 +106,14 @@ yy11: ++YYCURSOR; #line 70 "ext/phar/phar_path_check.re" { - if (*s == '/') { - s++; + if (**s == '/') { + (*s)++; + (*len)--; } *error = NULL; return pcr_is_ok; } -#line 116 "ext/phar/phar_path_check.c" +#line 117 "ext/phar/phar_path_check.c" yy13: yych = *++YYCURSOR; goto yy4; @@ -123,7 +124,7 @@ yy14: *error = "empty entry"; return pcr_err_empty_entry; } -#line 127 "ext/phar/phar_path_check.c" +#line 128 "ext/phar/phar_path_check.c" yy16: yych = *++YYCURSOR; if(yych <= 0x00) goto yy20; @@ -138,7 +139,7 @@ yy17: *error = "double slash"; return pcr_err_double_slash; } -#line 142 "ext/phar/phar_path_check.c" +#line 143 "ext/phar/phar_path_check.c" yy19: yych = *++YYCURSOR; if(yych <= 0x00) goto yy22; @@ -151,7 +152,7 @@ yy20: *error = "current directory reference"; return pcr_err_curr_dir; } -#line 155 "ext/phar/phar_path_check.c" +#line 156 "ext/phar/phar_path_check.c" yy22: ++YYCURSOR; #line 42 "ext/phar/phar_path_check.re" @@ -159,9 +160,9 @@ yy22: *error = "upper directory reference"; return pcr_err_up_dir; } -#line 163 "ext/phar/phar_path_check.c" +#line 164 "ext/phar/phar_path_check.c" } } -#line 80 "ext/phar/phar_path_check.re" +#line 81 "ext/phar/phar_path_check.re" } diff --git a/ext/phar/phar_path_check.re b/ext/phar/phar_path_check.re index 9f1e7efda3..1caac5c108 100755 --- a/ext/phar/phar_path_check.re +++ b/ext/phar/phar_path_check.re @@ -20,9 +20,9 @@ #include "phar_internal.h" -phar_path_check_result phar_path_check(const char *s, int *len, const char **error) +phar_path_check_result phar_path_check(char **s, int *len, const char **error) { - const unsigned char *p = (const unsigned char*)s; + const unsigned char *p = (const unsigned char*)*s; const unsigned char *m; #define YYCTYPE unsigned char #define YYCURSOR p @@ -60,16 +60,17 @@ ANY = .; return pcr_err_star; } "?" { - if (*s == '/') { - s++; + if (**s == '/') { + (*s)++; } - *len = (p - (const unsigned char*)s) -1; + *len = (p - (const unsigned char*)*s) -1; *error = NULL; return pcr_use_query; } END { - if (*s == '/') { - s++; + if (**s == '/') { + (*s)++; + (*len)--; } *error = NULL; return pcr_is_ok; diff --git a/ext/phar/tests/phar_offset_get_error.phpt b/ext/phar/tests/phar_offset_get_error.phpt new file mode 100755 index 0000000000..75d5e0af0b --- /dev/null +++ b/ext/phar/tests/phar_offset_get_error.phpt @@ -0,0 +1,37 @@ +--TEST-- +Phar: ignore filenames starting with / on offsetSet +--SKIPIF-- + + +--INI-- +phar.readonly=0 +phar.require_hash=1 +--FILE-- +getMessage() . "\n"; +} + +include($pname . $iname); +?> +===DONE=== +--CLEAN-- + +--EXPECT-- +Entry /error/ does not exist and cannot be created: phar error: invalid path "/error/" contains empty entry +foobar +===DONE=== -- 2.40.0