hi again, On Fri, Jan 23, 2009 at 08:23:59AM +0100, sean finney wrote: > it's unfortunate that there isn't a more surgical fix (301 insertions!), > but i'll take your word for it that it would be too complicated/dangerous > to try and modify virtual_file_ex() directly.
actually, i think i've found a slightly more graceful workaround :) since virtual_file_ex is to fragile to be changed, here's a patch that does the following as a workaround: - take a temporary copy of the filename - replace all instances of "^../", "/../", and "/..$" with "///". - pass this mangled filename to virtual_file_ex for normalization it seems virtual_file_ex can handle such a filename without problem, and with proper formatting the current patch only inserts 22 lines to php_zip.c. someone should probably double check this code for early-morning coding errors though :) what do you think? sean
--- ext/zip/php_zip.c.orig 2009-01-23 08:29:32.000000000 +0100 +++ ext/zip/php_zip.c 2009-01-23 08:56:42.000000000 +0100 @@ -142,6 +142,9 @@ char *path_cleaned; size_t path_cleaned_len; cwd_state new_state; + char *tmp_file = NULL; + char *tmp_needle = NULL; + int virtual_ret = 0; new_state.cwd = (char*)malloc(1); new_state.cwd[0] = '\0'; @@ -150,7 +153,25 @@ /* Clean/normlize the path and then transform any path (absolute or relative) to a path relative to cwd (../../mydir/foo.txt > mydir/foo.txt) */ - virtual_file_ex(&new_state, file, NULL, CWD_EXPAND); + tmp_file = strdup(file); + while (tmp_needle=strstr(tmp_file, "/../")) + { + *(tmp_needle+1)=*(tmp_needle+2)='/'; + } + if (strncmp(tmp_file, "..", 2) == 0 && (file_len == 2 || tmp_file[2] == '/')) + { + tmp_file[0]=tmp_file[1]='/'; + } + if (file_len > 3 && strncmp(&tmp_file[file_len-2], "..", 2) == 0) + { + tmp_file[file_len-1]=tmp_file[file_len-2]='/'; + } + virtual_ret = virtual_file_ex(&new_state, tmp_file, NULL, CWD_EXPAND); + free(tmp_file); + if (virtual_ret == 1) + { + return 0; + } path_cleaned = php_zip_make_relative_path(new_state.cwd, new_state.cwd_length); path_cleaned_len = strlen(path_cleaned);
signature.asc
Description: Digital signature