diff --git a/bins/unzip-mem.c b/bins/unzip-mem.c index c45cb72..ff564a5 100644 --- a/bins/unzip-mem.c +++ b/bins/unzip-mem.c @@ -88,10 +88,53 @@ static void zzip_mem_entry_pipe(ZZIP_MEM_DISK* disk, } } + + + +static inline void +remove_dotdotslash(char *path) +{ + /* Note: removing "../" from the path ALWAYS shortens the path, never adds to it! */ + char *dotdotslash; + int warned = 0; + + dotdotslash = path; + while ((dotdotslash = strstr(dotdotslash, "../")) != NULL) + { + /* + * Remove only if at the beginning of the pathname ("../path/name") + * or when preceded by a slash ("path/../name"), + * otherwise not ("path../name..")! + */ + if (dotdotslash == path || dotdotslash[-1] == '/') + { + char *src, *dst; + if (!warned) + { + /* Note: the first time through the pathname is still intact */ + fprintf(stderr, "Removing \"../\" path component(s) in %s\n", path); + warned = 1; + } + /* We cannot use strcpy(), as there "The strings may not overlap" */ + for (src = dotdotslash+3, dst=dotdotslash; (*dst = *src) != '\0'; src++, dst++) + ; + } + else + dotdotslash +=3; /* skip this instance to prevent infinite loop */ + } +} + static void zzip_mem_entry_make(ZZIP_MEM_DISK* disk, ZZIP_MEM_ENTRY* entry) { - FILE* file = fopen (entry->zz_name, "w"); + char name_stripped[PATH_MAX+1]; + FILE* file; + + strncpy(name_stripped, entry->zz_name, PATH_MAX); + name_stripped[PATH_MAX]='\0'; + remove_dotdotslash(name_stripped); + + file = fopen (name_stripped, "wb"); if (file) { zzip_mem_entry_pipe (disk, entry, file); fclose (file); } perror (entry->zz_name); if (status < EXIT_WARNINGS) status = EXIT_WARNINGS;