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:
80
zdump.c
80
zdump.c
@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user