diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 11088ead5b7..c1e8f316618 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -94,7 +94,8 @@ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_D { size_t to_read; HashTable *data = (HashTable *)stream->abstract; - char *key; + phar_zstr key; + char *str_key; uint keylen; ulong unused; @@ -104,13 +105,14 @@ static size_t phar_dir_read(php_stream *stream, char *buf, size_t count TSRMLS_D if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(data, &key, &keylen, &unused, 0, NULL)) { return 0; } + PHAR_STR(key, str_key); zend_hash_move_forward(data); to_read = MIN(keylen, count); if (to_read == 0 || count < keylen) { return 0; } memset(buf, 0, sizeof(php_stream_dirent)); - memcpy(((php_stream_dirent *) buf)->d_name, key, to_read); + memcpy(((php_stream_dirent *) buf)->d_name, str_key, to_read); ((php_stream_dirent *) buf)->d_name[to_read + 1] = '\0'; return sizeof(php_stream_dirent); @@ -186,10 +188,11 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) { HashTable *data; int dirlen = strlen(dir); - char *save, *found, *key; + phar_zstr key; + char *entry, *found, *save, *str_key; uint keylen; ulong unused; - char *entry; + ALLOC_HASHTABLE(data); zend_hash_init(data, 64, zend_get_hash_value, NULL, 0); @@ -203,8 +206,9 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(manifest, &key, &keylen, &unused, 0, NULL)) { break; } + PHAR_STR(key, str_key); if (keylen <= (uint)dirlen) { - if (keylen < (uint)dirlen || !strncmp(key, dir, dirlen)) { + if (keylen < (uint)dirlen || !strncmp(str_key, dir, dirlen)) { if (SUCCESS != zend_hash_move_forward(manifest)) { break; } @@ -213,27 +217,27 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) } if (*dir == '/') { /* root directory */ - if (NULL != (found = (char *) memchr(key, '/', keylen))) { + if (NULL != (found = (char *) memchr(str_key, '/', keylen))) { /* the entry has a path separator and is a subdirectory */ - entry = (char *) safe_emalloc(found - key, 1, 1); - memcpy(entry, key, found - key); - keylen = found - key; + entry = (char *) safe_emalloc(found - str_key, 1, 1); + memcpy(entry, str_key, found - str_key); + keylen = found - str_key; entry[keylen] = '\0'; } else { entry = (char *) safe_emalloc(keylen, 1, 1); - memcpy(entry, key, keylen); + memcpy(entry, str_key, keylen); entry[keylen] = '\0'; } goto PHAR_ADD_ENTRY; } else { - if (0 != memcmp(key, dir, dirlen)) { + if (0 != memcmp(str_key, dir, dirlen)) { /* entry in directory not found */ if (SUCCESS != zend_hash_move_forward(manifest)) { break; } continue; } else { - if (key[dirlen] != '/') { + if (str_key[dirlen] != '/') { if (SUCCESS != zend_hash_move_forward(manifest)) { break; } @@ -241,7 +245,7 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest TSRMLS_DC) } } } - save = key; + save = str_key; save += dirlen + 1; /* seek to just past the path separator */ if (NULL != (found = (char *) memchr(save, '/', keylen - dirlen - 1))) { /* is subdirectory */ @@ -289,7 +293,8 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char { php_url *resource = NULL; php_stream *ret; - char *internal_file, *key, *error; + char *internal_file, *error, *str_key; + phar_zstr key; uint keylen; ulong unused; phar_archive_data *phar; @@ -367,7 +372,8 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, char *path, char if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - if (keylen > (uint)i_len && 0 == memcmp(key, internal_file, i_len)) { + PHAR_STR(key, str_key); + if (keylen > (uint)i_len && 0 == memcmp(str_key, internal_file, i_len)) { /* directory found */ internal_file = estrndup(internal_file, i_len); diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index b92d61a4224..853cf1477d0 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -655,7 +655,8 @@ notfound: goto stat_entry; } else { phar_archive_data *phar = *pphar; - char *key; + phar_zstr key; + char *str_key; uint keylen; ulong unused; @@ -667,11 +668,12 @@ notfound: if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - if (!memcmp(actual, key, actual_len)) { + PHAR_STR(key, str_key); + if (!memcmp(actual, str_key, actual_len)) { efree(save2); efree(entry); /* directory found, all dirs have the same stat */ - if (key[actual_len] == '/') { + if (str_key[actual_len] == '/') { sb.st_size = 0; sb.st_mode = 0777; sb.st_mode |= S_IFDIR; /* regular directory */ diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 4e14d2bbb60..2ac7209f1c3 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -817,7 +817,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int register_alias = 1; temp_alias = 1; } - + /* we have 5 32-bit items plus 1 byte at least */ if (manifest_count > ((manifest_len - 10 - tmp_len) / (5 * 4 + 1))) { /* prevent serious memory issues */ @@ -1592,7 +1592,8 @@ woohoo: return FAILURE; } } else { - char *key; + phar_zstr key; + char *str_key; uint keylen; ulong unused; @@ -1602,11 +1603,13 @@ woohoo: break; } + PHAR_STR(key, str_key); + if (keylen > (uint) filename_len) { zend_hash_move_forward(&(PHAR_GLOBALS->phar_fname_map)); continue; } - if (!memcmp(filename, key, keylen) && ((uint)filename_len == keylen + if (!memcmp(filename, str_key, keylen) && ((uint)filename_len == keylen || filename[keylen] == '/' || filename[keylen] == '\0')) { if (FAILURE == zend_hash_get_current_data(&(PHAR_GLOBALS->phar_fname_map), (void **) &pphar)) { break; @@ -2847,7 +2850,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type } } else if (phar->flags & PHAR_FILE_COMPRESSION_MASK) { /* compressed phar */ -#if PHP_VERSION_ID >= 50300 && PHP_VERSION_ID < 60000 +#if PHP_VERSION_ID >= 50300 file_handle->type = ZEND_HANDLE_STREAM; file_handle->free_filename = 0; file_handle->handle.stream.handle = phar; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 1aa54251250..cec12ead319 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -354,8 +354,17 @@ extern char *(*phar_save_resolve_path)(const char *filename, int filename_len TS # endif #endif -BEGIN_EXTERN_C() +#if PHP_VERSION_ID >= 60000 +typedef zstr phar_zstr; +#define PHAR_STR(a, b) \ + spprintf(&b, 0, "%r", a.s); +#else +typedef char *phar_zstr; +#define PHAR_STR(a, b) \ + b = a; +#endif +BEGIN_EXTERN_C() #ifdef PHP_WIN32 char *tsrm_strtok_r(char *s, const char *delim, char **last); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 98b602adbc8..1e37e5d8c46 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -778,7 +778,7 @@ PHP_METHOD(Phar, webPhar) mime.len = Z_STRLEN_PP(val); \ } \ mime.type = ret; \ - zend_hash_update(&mimetypes, key, keylen-1, (void *)&mime, sizeof(phar_mime_type), NULL); + zend_hash_update(&mimetypes, str_key, keylen-1, (void *)&mime, sizeof(phar_mime_type), NULL); if (mimeoverride) { if (!zend_hash_num_elements(Z_ARRVAL_P(mimeoverride))) { @@ -786,9 +786,11 @@ PHP_METHOD(Phar, webPhar) } for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(mimeoverride)); SUCCESS == zend_hash_has_more_elements(Z_ARRVAL_P(mimeoverride)); zend_hash_move_forward(Z_ARRVAL_P(mimeoverride))) { zval **val; - char *key; + phar_zstr key; + char *str_key; uint keylen; ulong intkey; + if (HASH_KEY_IS_LONG == zend_hash_get_current_key_ex(Z_ARRVAL_P(mimeoverride), &key, &keylen, &intkey, 0, NULL)) { zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Key of MIME type overrides array must be a file extension, was \"%d\"", intkey); phar_entry_delref(phar TSRMLS_CC); @@ -797,8 +799,11 @@ PHP_METHOD(Phar, webPhar) #endif RETURN_FALSE; } + + PHAR_STR(key, str_key); + if (FAILURE == zend_hash_get_current_data(Z_ARRVAL_P(mimeoverride), (void **) &val)) { - zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Failed to retrieve Mime type for extension \"%s\"", key); + zend_throw_exception_ex(phar_ce_PharException, 0 TSRMLS_CC, "Failed to retrieve Mime type for extension \"%s\"", str_key); phar_entry_delref(phar TSRMLS_CC); #ifdef PHP_WIN32 efree(fname); @@ -1114,11 +1119,8 @@ PHP_METHOD(Phar, __construct) return; } -#if PHP_VERSION_ID >= 60000 - objname = phar_obj->std.ce->name.s; -#else - objname = phar_obj->std.ce->name; -#endif + PHAR_STR(phar_obj->std.ce->name, objname); + if (!strncmp(objname, "PharData", 8)) { is_data = 1; } else { @@ -1315,7 +1317,9 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ phar_entry_data *data; php_stream *fp; long contents_len; - char *fname, *error, *str_key, *base = p_obj->b, *opened, *save = NULL, *temp = NULL; + char *fname, *error, *base = p_obj->b, *opened, *save = NULL, *temp = NULL; + phar_zstr key; + char *str_key; zend_class_entry *ce = p_obj->c; phar_archive_object *phar_obj = p_obj->p; char *str = "[stream]"; @@ -1339,10 +1343,14 @@ static int phar_build(zend_object_iterator *iter, void *puser TSRMLS_DC) /* {{{ return ZEND_HASH_APPLY_STOP; } if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } + + PHAR_STR(key, str_key); + if (key_type == HASH_KEY_IS_LONG) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; @@ -1438,10 +1446,14 @@ phar_spl_fileinfo: } } else { if (iter->funcs->get_current_key) { - key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + key_type = iter->funcs->get_current_key(iter, &key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { return ZEND_HASH_APPLY_STOP; } + + PHAR_STR(key, str_key); + if (key_type == HASH_KEY_IS_LONG) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Iterator %s returned an invalid key (must return a string)", ce->name); return ZEND_HASH_APPLY_STOP; diff --git a/ext/phar/shortarc.php b/ext/phar/shortarc.php index fa526366466..748afeda2e2 100644 --- a/ext/phar/shortarc.php +++ b/ext/phar/shortarc.php @@ -268,7 +268,7 @@ class Extract_Phar $stat[7] . ")"); } - if ($entry[3] != sprintf("%u", crc32($data) & 0xffffffff)) { + if ($entry[3] != sprintf("%u", crc32((binary)$data) & 0xffffffff)) { die("Invalid internal .phar file (checksum error)"); } diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 3d9f14e4d45..e6c57a89ab7 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -501,7 +501,8 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context TSRMLS_DC) /* {{{ */ { php_url *resource = NULL; - char *internal_file, *key, *error; + phar_zstr key; + char *internal_file, *error, *str_key; uint keylen; ulong unused; phar_archive_data *phar; @@ -562,9 +563,10 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, if (HASH_KEY_NON_EXISTANT != zend_hash_get_current_key_ex( &phar->manifest, &key, &keylen, &unused, 0, NULL)) { - if (keylen >= (uint)internal_file_len && 0 == memcmp(internal_file, key, internal_file_len)) { + PHAR_STR(key, str_key); + if (keylen >= (uint)internal_file_len && 0 == memcmp(internal_file, str_key, internal_file_len)) { /* directory found, all dirs have the same stat */ - if (key[internal_file_len] == '/') { + if (str_key[internal_file_len] == '/') { phar_dostat(phar, NULL, ssb, 1, phar->alias, phar->alias_len TSRMLS_CC); php_url_free(resource); return SUCCESS; @@ -577,7 +579,8 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, } /* check for mounted directories */ if (phar->mounted_dirs.arBuckets && zend_hash_num_elements(&phar->mounted_dirs)) { - char *key; + phar_zstr key; + char *str_key; ulong unused; uint keylen; @@ -586,7 +589,8 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, if (HASH_KEY_NON_EXISTANT == zend_hash_get_current_key_ex(&phar->mounted_dirs, &key, &keylen, &unused, 0, NULL)) { break; } - if ((int)keylen >= internal_file_len || strncmp(key, internal_file, keylen)) { + PHAR_STR(key, str_key); + if ((int)keylen >= internal_file_len || strncmp(str_key, internal_file, keylen)) { continue; } else { char *test; @@ -594,7 +598,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, char *url, int flags, phar_entry_info *entry; php_stream_statbuf ssbi; - if (SUCCESS != zend_hash_find(&phar->manifest, key, keylen, (void **) &entry)) { + if (SUCCESS != zend_hash_find(&phar->manifest, str_key, keylen, (void **) &entry)) { goto free_resource; } if (!entry->tmp || !entry->is_mounted) { diff --git a/ext/phar/stub.h b/ext/phar/stub.h index f5858e2f07c..104a8baa639 100644 --- a/ext/phar/stub.h +++ b/ext/phar/stub.h @@ -25,9 +25,9 @@ static inline void phar_get_stub(const char *index_php, const char *web, size_t static const char newstub1_1[] = "Extract_Phar::$temp)) {\nheader('HTTP/1.0 404 Not Found');\necho \"\\n
\\n