Skip to content

Instantly share code, notes, and snippets.

@smalyshev
Created August 2, 2015 06:11
Show Gist options
  • Save smalyshev/2d63ef849583b3097560 to your computer and use it in GitHub Desktop.
Save smalyshev/2d63ef849583b3097560 to your computer and use it in GitHub Desktop.
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index 8cfe0c8..7bbea5c 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -4200,6 +4200,9 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
char *fullpath;
const char *slash;
mode_t mode;
+ cwd_state new_state;
+ char *filename;
+ size_t filename_len;
if (entry->is_mounted) {
/* silently ignore mounted entries */
@@ -4209,8 +4212,22 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) {
return SUCCESS;
}
+ /* strip .. from path and restrict it to be under dest directory */
+ new_state.cwd = (char*)malloc(2);
+ new_state.cwd[0] = '/';
+ new_state.cwd[1] = '\0';
+ new_state.cwd_length = 1;
- len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename);
+ if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND TSRMLS_CC) != 0 ||
+ new_state.cwd_length <= 1) {
+ spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
+ free(new_state.cwd);
+ return FAILURE;
+ }
+ filename = new_state.cwd + 1;
+ filename_len = new_state.cwd_length - 1;
+
+ len = spprintf(&fullpath, 0, "%s/%s", dest, filename);
if (len >= MAXPATHLEN) {
char *tmp;
@@ -4224,18 +4241,21 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath);
}
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
if (!len) {
spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename);
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) {
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath);
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
@@ -4243,14 +4263,15 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) {
spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath);
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
/* perform dirname */
- slash = zend_memrchr(entry->filename, '/', entry->filename_len);
+ slash = zend_memrchr(filename, '/', filename_len);
if (slash) {
- fullpath[dest_len + (slash - entry->filename) + 1] = '\0';
+ fullpath[dest_len + (slash - filename) + 1] = '\0';
} else {
fullpath[dest_len] = '\0';
}
@@ -4260,23 +4281,27 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
} else {
if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
efree(fullpath);
+ free(new_state.cwd);
return FAILURE;
}
}
}
if (slash) {
- fullpath[dest_len + (slash - entry->filename) + 1] = '/';
+ fullpath[dest_len + (slash - filename) + 1] = '/';
} else {
fullpath[dest_len] = '/';
}
+ filename = NULL;
+ free(new_state.cwd);
/* it is a standalone directory, job done */
if (entry->is_dir) {
efree(fullpath);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment