Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Buffer overflow bug in globbing
- X-seq: zsh-workers 2659
- From: Zoltan Hidvegi <hzoli@xxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxxx (Zsh hacking and development)
- Subject: Buffer overflow bug in globbing
- Date: Sun, 29 Dec 1996 03:07:37 +0100 (MET)
Just try
% echo *<ESC>2<ESC>0<ESC>6<ESC>00 <RETURN>
(echo * followed by 2060 zeros.) You'll get a coredump.
Fix is included below. This should be applied to zsh-3.0.2 as well.
It's a bit embarrasing that this bug together with the previous case bug
causes a coredump while running configure for bash-2.0.
This fixes an other minor bug:
% echo ([foo)bar
should print bad pattern error.
The patch adds the ztrduppfx() and dupstrpfx() function to utils.c to
duplicate the prefix of a string. Only the later function is used now
but later I'll replace some
sav = *s;
*s = '\0';
t = ztrdup(*p);
*s = sav;
calls to ztrduppfx(). The advantage of these prefix dup functions is
that they are faster and can be used on const char * strings.
Zoltan
*** Src/glob.c 1996/12/25 16:04:45 3.1.1.2
--- Src/glob.c 1996/12/29 01:34:59
***************
*** 1924,1933 ****
parsecomp(void)
{
Comp c = (Comp) alloc(sizeof *c), c1, c2;
! char cstr[PATH_MAX * 2], *s = cstr, *ls = NULL;
/* In case of alternatives, code coming up is stored in tail. */
c->next = tail;
while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
(unset(EXTENDEDGLOB) || *pptr != Tilde ||
--- 1924,1934 ----
parsecomp(void)
{
Comp c = (Comp) alloc(sizeof *c), c1, c2;
! char *cstr, *ls = NULL;
/* In case of alternatives, code coming up is stored in tail. */
c->next = tail;
+ cstr = pptr;
while (*pptr && (mode || *pptr != '/') && *pptr != Bar &&
(unset(EXTENDEDGLOB) || *pptr != Tilde ||
***************
*** 1938,1949 ****
*/
if (*pptr == Hat && isset(EXTENDEDGLOB)) {
/* negate remaining pattern */
- *s++ = Hat;
- *s++ = '\0';
pptr++;
if (!(c->next = parsecomp()))
return NULL;
- c->str = dupstring(cstr);
return c;
}
if (*pptr == Star && pptr[1] &&
--- 1939,1948 ----
*/
if (*pptr == Hat && isset(EXTENDEDGLOB)) {
/* negate remaining pattern */
pptr++;
+ c->str = dupstrpfx(cstr, pptr - cstr);
if (!(c->next = parsecomp()))
return NULL;
return c;
}
if (*pptr == Star && pptr[1] &&
***************
*** 1954,1960 ****
* (zero or more repetitions) of the single character pattern
* operator `?'.
*/
! *s++ = '\0';
pptr++;
c1 = (Comp) alloc(sizeof *c1);
*(c1->str = dupstring("?")) = Quest;
--- 1953,1959 ----
* (zero or more repetitions) of the single character pattern
* operator `?'.
*/
! c->str = dupstrpfx(cstr, pptr - cstr);
pptr++;
c1 = (Comp) alloc(sizeof *c1);
*(c1->str = dupstring("?")) = Quest;
***************
*** 1963,1969 ****
return NULL;
c1->next = c2;
c->next = c1;
- c->str = dupstring(cstr);
return c;
}
if (*pptr == Inpar) {
--- 1962,1967 ----
***************
*** 1994,2068 ****
/* ...before going back and parsing inside the group. */
endp = pptr;
pptr = startp;
pptr++;
- *s++ = '\0';
c->next = (Comp) alloc(sizeof *c);
! c->next->left = parsecompsw(0);
/* Remember closures for group. */
if (dpnd)
c->next->stat |= (dpnd == 2) ? C_TWOHASH : C_ONEHASH;
c->next->next = dpnd ? c1 : (Comp) alloc(sizeof *c);
pptr = endp;
tail = stail;
- c->str = dupstring(cstr);
return c;
}
if (*pptr == Pound && isset(EXTENDEDGLOB)) {
/* repeat whatever we've just had (ls) zero or more times */
- *s = '\0';
- pptr++;
if (!ls)
return NULL;
if (*pptr == Pound) {
/* need one or more matches: cheat by copying previous char */
pptr++;
c->next = c1 = (Comp) alloc(sizeof *c);
! c1->str = dupstring(ls);
} else
c1 = c;
! c1->next = c2 = (Comp) alloc(sizeof *c);
! c2->str = dupstring(ls);
c2->stat |= C_ONEHASH;
/* parse the rest of the pattern and return. */
c2->next = parsecomp();
if (!c2->next)
return NULL;
! *ls++ = '\0';
! c->str = dupstring(cstr);
return c;
}
! ls = s; /* whatever we just parsed */
if (*pptr == Inang) {
/* Numeric glob */
int dshct;
dshct = (pptr[1] == Outang);
! *s++ = *pptr++;
! while (*pptr && (*s++ = *pptr++) != Outang)
! if (s[-1] == '-')
! dshct++;
! else if (!idigit(s[-1]))
break;
! if (s[-1] != Outang)
return NULL;
} else if (*pptr == Inbrack) {
/* Character set: brackets had better match */
! while (*pptr && (*s++ = *pptr++) != Outbrack);
! if (s[-1] != Outbrack)
return NULL;
! } else if (itok(*pptr) && *pptr != Star && *pptr != Quest) {
/* something that can be tokenised which isn't otherwise special */
! *s++ = ztokens[*pptr++ - Pound];
! } else {
! /* any other character */
! *s++ = *pptr++;
! }
}
/* mark if last pattern component in path component or pattern */
if (*pptr == '/' || !*pptr)
c->stat |= C_LAST;
! *s++ = '\0';
! c->str = dupstring(cstr);
return c;
}
--- 1992,2062 ----
/* ...before going back and parsing inside the group. */
endp = pptr;
pptr = startp;
+ c->str = dupstrpfx(cstr, pptr - cstr);
pptr++;
c->next = (Comp) alloc(sizeof *c);
! if (!(c->next->left = parsecompsw(0)))
! return NULL;
/* Remember closures for group. */
if (dpnd)
c->next->stat |= (dpnd == 2) ? C_TWOHASH : C_ONEHASH;
c->next->next = dpnd ? c1 : (Comp) alloc(sizeof *c);
pptr = endp;
tail = stail;
return c;
}
if (*pptr == Pound && isset(EXTENDEDGLOB)) {
/* repeat whatever we've just had (ls) zero or more times */
if (!ls)
return NULL;
+ c2 = (Comp) alloc(sizeof *c);
+ c2->str = dupstrpfx(ls, pptr - ls);
+ pptr++;
if (*pptr == Pound) {
/* need one or more matches: cheat by copying previous char */
pptr++;
c->next = c1 = (Comp) alloc(sizeof *c);
! c1->str = c2->str;
} else
c1 = c;
! c1->next = c2;
c2->stat |= C_ONEHASH;
/* parse the rest of the pattern and return. */
c2->next = parsecomp();
if (!c2->next)
return NULL;
! c->str = dupstrpfx(cstr, ls - cstr);
return c;
}
! ls = pptr; /* whatever we just parsed */
if (*pptr == Inang) {
/* Numeric glob */
int dshct;
dshct = (pptr[1] == Outang);
! while (*++pptr && *pptr != Outang)
! if (*pptr == '-' && !dshct)
! dshct = 1;
! else if (!idigit(*pptr))
break;
! if (*pptr != Outang)
return NULL;
} else if (*pptr == Inbrack) {
/* Character set: brackets had better match */
! while (*++pptr && *pptr != Outbrack)
! if (itok(*pptr))
! *pptr = ztokens[*pptr - Pound];
! if (*pptr != Outbrack)
return NULL;
! } else if (itok(*pptr) && *pptr != Star && *pptr != Quest)
/* something that can be tokenised which isn't otherwise special */
! *pptr = ztokens[*pptr - Pound];
! pptr++;
}
/* mark if last pattern component in path component or pattern */
if (*pptr == '/' || !*pptr)
c->stat |= C_LAST;
! c->str = dupstrpfx(cstr, pptr - cstr);
return c;
}
*** Src/utils.c 1996/12/26 22:43:13 3.1.1.4
--- Src/utils.c 1996/12/29 01:00:41
***************
*** 3185,3190 ****
--- 3185,3212 ----
return 0;
}
+ /**/
+ char *
+ dupstrpfx(const char *s, int len)
+ {
+ char *r = ncalloc(len + 1);
+
+ memcpy(r, s, len);
+ r[len] = '\0';
+ return r;
+ }
+
+ /**/
+ char *
+ ztrduppfx(const char *s, int len)
+ {
+ char *r = zalloc(len + 1);
+
+ memcpy(r, s, len);
+ r[len] = '\0';
+ return r;
+ }
+
#ifdef DEBUG
/**/
Messages sorted by:
Reverse Date,
Date,
Thread,
Author