Skip to content

Commit

Permalink
Fix int overflow with very long string
Browse files Browse the repository at this point in the history
Problem indirectly reported by Kees Dekker in:
http://mm.icann.org/pipermail/tz/2015-July/022527.html
* localtime.c (tzparse): Check for sp->chars overflow
before converting length to 'int', to avoid undefined behavior
when the input string has more than INT_MAX bytes.
  • Loading branch information
eggert committed Jul 28, 2015
1 parent dc0893e commit fb1560a
Showing 1 changed file with 11 additions and 8 deletions.
19 changes: 11 additions & 8 deletions localtime.c
Expand Up @@ -986,17 +986,16 @@ tzparse(const char *name, struct state *sp, bool lastditch)
const char * dstname;
size_t stdlen;
size_t dstlen;
size_t charcnt;
int_fast32_t stdoffset;
int_fast32_t dstoffset;
register char * cp;
register bool load_ok;

stdname = name;
if (lastditch) {
stdlen = strlen(name); /* length of standard zone name */
stdlen = sizeof gmt - 1;
name += stdlen;
if (stdlen >= sizeof sp->chars)
stdlen = (sizeof sp->chars) - 1;
stdoffset = 0;
} else {
if (*name == '<') {
Expand All @@ -1017,6 +1016,9 @@ tzparse(const char *name, struct state *sp, bool lastditch)
if (name == NULL)
return false;
}
charcnt = stdlen + 1;
if (sizeof sp->chars < charcnt)
return false;
load_ok = tzload(TZDEFRULES, sp, false) == 0;
if (!load_ok)
sp->leapcnt = 0; /* so, we're off a little */
Expand All @@ -1033,6 +1035,11 @@ tzparse(const char *name, struct state *sp, bool lastditch)
name = getzname(name);
dstlen = name - dstname; /* length of DST zone name */
}
if (!dstlen)
return false;
charcnt += dstlen + 1;
if (sizeof sp->chars < charcnt)
return false;
if (*name != '\0' && *name != ',' && *name != ';') {
name = getoffset(name, &dstoffset);
if (name == NULL)
Expand Down Expand Up @@ -1193,11 +1200,7 @@ tzparse(const char *name, struct state *sp, bool lastditch)
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
sp->defaulttype = 0;
}
sp->charcnt = stdlen + 1;
if (dstlen != 0)
sp->charcnt += dstlen + 1;
if ((size_t) sp->charcnt > sizeof sp->chars)
return false;
sp->charcnt = charcnt;
cp = sp->chars;
memcpy(cp, stdname, stdlen);
cp += stdlen;
Expand Down

0 comments on commit fb1560a

Please sign in to comment.