1
0
mirror of https://frontier.innolan.net/rainlance/amiga-tz.git synced 2025-11-23 05:42:12 +00:00

* zdump.c: Avoid crashes on unlikely integer overflows.

(longest): Now int, since it can't exceed INT_MAX.
(sumsize, settimezone): New functions.
(main): Don't let 'longest' exceed INT_MAX.  Use settimezone.
(show): Remove no-longer-necessary cast that formerly had undefined
behavior if 'longest' exceeded INT_MAX.
This commit is contained in:
Paul Eggert
2014-08-21 14:07:55 -07:00
parent b2290be9d6
commit 161539d6d9

80
zdump.c
View File

@ -220,7 +220,7 @@ static time_t const absolute_max_time =
((time_t) -1 < 0
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
: -1);
static size_t longest;
static int longest;
static char * progname;
static bool warned;
static bool errout;
@ -252,6 +252,52 @@ is_alpha(char a)
}
}
/* Return A + B, exiting if the result would overflow. */
static size_t
sumsize(size_t a, size_t b)
{
size_t sum = a + b;
if (sum < a) {
fprintf(stderr, "%s: size overflow\n", progname);
exit(EXIT_FAILURE);
}
return sum;
}
/* Set the global time zone to VAL, exiting on memory allocation failure. */
static void
settimezone(char const *val)
{
static char **fakeenv;
char **env = fakeenv;
char *oldstorage = env ? env[0] : 0;
char *env0;
if (! env) {
char **e = environ;
int to;
while (*e++)
continue;
env = malloc(sumsize(sizeof *environ,
(e - environ) * sizeof *environ));
if (! env) {
perror(progname);
exit(EXIT_FAILURE);
}
to = 1;
for (e = environ; (env[to] = *e); e++)
to += strncmp(*e, "TZ=", 3) != 0;
}
env0 = malloc(sumsize(sizeof "TZ=", strlen(val)));
if (! env0) {
perror(progname);
exit(EXIT_FAILURE);
}
env[0] = strcat(strcpy(env0, "TZ="), val);
environ = fakeenv = env;
free(oldstorage);
}
#ifndef TYPECHECK
#define my_localtime localtime
#else /* !defined TYPECHECK */
@ -358,7 +404,6 @@ main(int argc, char *argv[])
register char * cuttimes;
register time_t cutlotime;
register time_t cuthitime;
register char ** fakeenv;
time_t now;
time_t t;
time_t newt;
@ -459,33 +504,16 @@ main(int argc, char *argv[])
}
now = time(NULL);
longest = 0;
for (i = optind; i < argc; ++i)
if (strlen(argv[i]) > longest)
longest = strlen(argv[i]);
{
register int from;
register int to;
for (i = 0; environ[i] != NULL; ++i)
continue;
fakeenv = malloc((i + 2) * sizeof *fakeenv);
if (fakeenv == NULL
|| (fakeenv[0] = malloc(longest + 4)) == NULL) {
perror(progname);
return EXIT_FAILURE;
}
to = 0;
strcpy(fakeenv[to++], "TZ=");
for (from = 0; environ[from] != NULL; ++from)
if (strncmp(environ[from], "TZ=", 3) != 0)
fakeenv[to++] = environ[from];
fakeenv[to] = NULL;
environ = fakeenv;
for (i = optind; i < argc; i++) {
size_t arglen = strlen(argv[i]);
if (longest < arglen)
longest = arglen < INT_MAX ? arglen : INT_MAX;
}
for (i = optind; i < argc; ++i) {
static char buf[MAX_STRING_LENGTH];
strcpy(&fakeenv[0][3], argv[i]);
settimezone(argv[i]);
if (! (vflag | Vflag)) {
show(argv[i], now, false);
continue;
@ -659,7 +687,7 @@ show(char *zone, time_t t, bool v)
{
register struct tm * tmp;
printf("%-*s ", (int) longest, zone);
printf("%-*s ", longest, zone);
if (v) {
tmp = gmtime(&t);
if (tmp == NULL) {