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++ = '.';
|