$NetBSD: patch-ad,v 1.1.2.2 2008/06/08 12:46:49 tron Exp $ --- star/extract.c.orig 2002-05-02 22:02:41.000000000 +0200 +++ star/extract.c @@ -92,6 +92,7 @@ EXPORT int xt_file __PR((FINFO * info, int (*)(void *, char *, int), void *arg, int amt, char* text)); EXPORT void skip_slash __PR((FINFO * info)); +LOCAL BOOL has_dotdot __PR((char *name)); EXPORT void extract(vhname) @@ -152,6 +153,12 @@ extract(vhname) if (is_symlink(&finfo) && same_symlink(&finfo)) { continue; } + if (!interactive && has_dotdot(finfo.f_name)) { + errmsgno(EX_BAD, "'%s' contains '..', skipping ...\n", + finfo.f_name); + void_file(&finfo); + return (FALSE); + } if (interactive && !ia_change(ptb, &finfo)) { if (!nflag) fprintf(vpr, "Skipping ...\n"); @@ -169,6 +176,12 @@ extract(vhname) if (!make_dir(&finfo)) continue; } else if (is_link(&finfo)) { + if (!interactive && has_dotdot(finfo.f_lname)) { + errmsgno(EX_BAD, "'%s' contains '..', " + "skipping ...\n", finfo.f_lname); + void_file(&finfo); + return (FALSE); + } if (!make_link(&finfo)) continue; } else if (is_symlink(&finfo)) { @@ -830,3 +843,25 @@ skip_slash(info) while (info->f_lname[0] == '/') info->f_lname++; } + +LOCAL BOOL +has_dotdot(name) + char *name; +{ + register char *p = name; + + while (*p) { + if ((p[0] == '.' && p[1] == '.') && + (p[2] == '/' || p[2] == '\0')) { + return (TRUE); + } + do { + if (*p++ == '\0') + return (FALSE); + } while (*p != '/'); + p++; + while (*p && *p == '/') /* Skip multiple slashes */ + p++; + } + return (FALSE); +}