summaryrefslogtreecommitdiffstats
path: root/app-arch/unzip/files/unzip-5.50-dotdot.patch
blob: 962a302f1b1ec8916ed928c1ecca681539b9d7da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
Only in unzip-5.50-lhh/: cscope.files
Only in unzip-5.50-lhh/: cscope.out
diff -ur unzip-5.50/unix/unix.c unzip-5.50-lhh/unix/unix.c
--- unzip-5.50/unix/unix.c	2002-01-21 17:54:42.000000000 -0500
+++ unzip-5.50-lhh/unix/unix.c	2003-06-11 18:35:38.000000000 -0400
@@ -421,7 +421,8 @@
  */
 {
     char pathcomp[FILNAMSIZ];      /* path-component buffer */
-    char *pp, *cp=(char *)NULL;    /* character pointers */
+    char *pp, *cp=(char *)NULL,    /* character pointers */
+         *dp=(char *)NULL;
     char *lastsemi=(char *)NULL;   /* pointer to last semi-colon in pathcomp */
 #ifdef ACORN_FTYPE_NFS
     char *lastcomma=(char *)NULL;  /* pointer to last comma in pathcomp */
@@ -429,6 +430,7 @@
 #endif
     int quote = FALSE;             /* flags */
     int killed_ddot = FALSE;       /* is set when skipping "../" pathcomp */
+    int snarf_ddot = FALSE;	   /* Is set while scanning for "../" */
     int error = MPN_OK;
     register unsigned workch;      /* hold the character being tested */
 
@@ -467,6 +469,9 @@
     while ((workch = (uch)*cp++) != 0) {
 
         if (quote) {                 /* if character quoted, */
+	    if ((pp == pathcomp) && (workch == '.'))
+		/* Oh no you don't... */
+		goto ddot_hack;
             *pp++ = (char)workch;    /*  include it literally */
             quote = FALSE;
         } else
@@ -481,15 +486,44 @@
                 break;
 
             case '.':
-                if (pp == pathcomp) {   /* nothing appended yet... */
+                if (pp == pathcomp) {
+ddot_hack:
+		    /* nothing appended yet... */
                     if (*cp == '/') {   /* don't bother appending "./" to */
                         ++cp;           /*  the path: skip behind the '/' */
                         break;
-                    } else if (!uO.ddotflag && *cp == '.' && cp[1] == '/') {
-                        /* "../" dir traversal detected */
-                        cp += 2;        /*  skip over behind the '/' */
-                        killed_ddot = TRUE; /*  set "show message" flag */
-                        break;
+                    } else if (!uO.ddotflag) {
+
+			/*
+			 * SECURITY: Skip past control characters if the user
+			 * didn't OK use of absolute pathnames. lhh - this is
+			 * a very quick, ugly, inefficient fix.
+			 */
+			dp = cp;
+			do {
+			    workch = (uch)(*dp);
+			    if (workch == '/' && snarf_ddot) {
+                                /* "../" dir traversal detected */
+                                cp = dp + 1;      /* skip past the '/' */
+                                killed_ddot = TRUE; /* set "show msg" flag */
+                                break;
+                            } else if (workch == '.' && !snarf_ddot) {
+				snarf_ddot = TRUE;
+                	    } else if (isprint(workch) ||
+				       ((workch > 127) && (workch <= 254))) {
+				/*
+				 * Since we found a printable, non-ctrl char,
+				 * we can stop looking for '../', the amount
+				 * in ../!
+				 */
+			        break;
+			    }
+
+			    dp++;
+                        } while (*dp != 0);
+
+			if (killed_ddot)
+			    break;
                     }
                 }
                 *pp++ = '.';