(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. --- zdump.c | 82 ++++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 56 insertions(+), 26 deletions(-) diff --git a/zdump.c b/zdump.c index 08323c1..f5a4dff 100644 --- a/zdump.c +++ b/zdump.c @@ -207,7 +207,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; @@ -239,6 +239,54 @@ 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); + } + strcpy(env0, "TZ="); + strcat(env0, val); + env[0] = env0; + environ = fakeenv = env; + free(oldstorage); +} + #ifndef TYPECHECK #define my_localtime localtime #else /* !defined TYPECHECK */ @@ -345,7 +393,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; @@ -446,33 +493,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; @@ -646,7 +676,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) { -- 1.9.1