--- /n/sources/plan9/sys/src/cmd/gzip/unzip.c Wed Jun 7 17:23:05 2000 +++ /sys/src/cmd/gzip/unzip.c Tue Sep 22 00:00:00 2026 @@ -26,6 +26,7 @@ static int unzipEntry(Biobuf *bin, ZipHead *czh); static int unztable(Biobuf *bin, char *file); static int wantFile(char *file); +static int badname(char *file); static void *emalloc(ulong); static void error(char*, ...); @@ -420,6 +421,11 @@ fd = -1; if(wantFile(zh.file)){ + if(badname(zh.file)){ + fprint(2, "unzip: refusing to extract %s\n", zh.file); + free(zh.file); + return 1; + } if(verbose) fprint(2, "extracting %s\n", zh.file); @@ -504,6 +510,22 @@ } static int +badname(char *file) +{ + char *p; + + if(file[0] == '/' || file[0] == '#') + return 1; + for(p = file; p != nil; p = strchr(p, '/')){ + while(*p == '/') + p++; + if(strcmp(p, "..") == 0 || strncmp(p, "../", 3) == 0) + return 1; + } + return 0; +} + +static int wantFile(char *file) { int i, n; --- /n/sources/plan9/sys/man/1/gzip Tue Sep 22 06:04:31 2026 +++ /sys/man/1/gzip Tue Sep 22 00:00:00 2026 @@ -158,6 +158,9 @@ extracts files from an archive created by .IR zip . If no files are named as arguments, all of files in the archive are extracted. +An entry whose name is absolute, or leads out of the current directory through +.BR .. , +is not extracted. A directory's name implies all recursively contained files and subdirectories. .I Zip is the