On Mon, Jun 14, 2004 at 08:11:26PM -0700, Ken Pizzini wrote:
That might work, depending on the local implementation of asctime(), but I'd feel more comfortable with a patch that takes care to avoid passing a NULL to asctime() in the first place. Perhaps this patch instead?
No, that patch wasn't right either: it did protect the asctime() calls fine, but it still left zdump.c with many potential dereferences of NULL localtime() result pointers. I'm not completely satisfied with how the code resulting from the patch below handles things, but at least it now completely avoids dereferencing these NULLs... (The attached patch is against a fresh copy of zdump.c from tzcode2004a; i.e., it is *not* incremental to either of the previous two patches circulated on the list.) --Ken Pizzini --- zdump.c-orig 2004-03-02 06:52:38.000000000 -0800 +++ zdump.c 2004-06-14 21:24:11.735549152 -0700 @@ -1,4 +1,4 @@ -static char elsieid[] = "@(#)zdump.c 7.31"; +static char elsieid[] = "@(#)zdump.c 7.32"; /* ** This code has been made independent of the rest of the time @@ -129,6 +129,7 @@ static size_t longest; static char * progname; static void show P((char * zone, time_t t, int v)); +static void complain P((time_t t)); int main(argc, argv) @@ -148,6 +149,7 @@ time_t hibit; struct tm tm; struct tm newtm; + struct tm *tmp; INITIALIZE(cuttime); #if HAVE_GETTEXT - 0 @@ -230,7 +232,12 @@ show(argv[i], t, TRUE); t += SECSPERHOUR * HOURSPERDAY; show(argv[i], t, TRUE); - tm = *localtime(&t); + tmp = localtime(&t); + if (tmp == NULL) { + complain(t); + continue; + } + tm = *tmp; (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); for ( ; ; ) { if (cutoff != NULL && t >= cuttime) @@ -240,12 +247,22 @@ break; if (newt <= t) break; - newtm = *localtime(&newt); + tmp = localtime(&newt); + if (tmp == NULL) { + complain(newt); + break; + } + newtm = *tmp; if (delta(&newtm, &tm) != (newt - t) || newtm.tm_isdst != tm.tm_isdst || strcmp(abbr(&newtm), buf) != 0) { newt = hunt(argv[i], t, newt); - newtm = *localtime(&newt); + tmp = localtime(&newt); + if (tmp == NULL) { + complain(newt); + break; + } + newtm = *tmp; (void) strncpy(buf, abbr(&newtm), (sizeof buf) - 1); } @@ -284,9 +301,15 @@ time_t t; struct tm lotm; struct tm tm; + struct tm *tmp; static char loab[MAX_STRING_LENGTH]; - lotm = *localtime(&lot); + tmp = localtime(&lot); + if (tmp == NULL) { + complain(lot); + return lot; + } + lotm = *tmp; (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1); while ((hit - lot) >= 2) { t = lot / 2 + hit / 2; @@ -294,7 +317,12 @@ ++t; else if (t >= hit) --t; - tm = *localtime(&t); + tmp = localtime(&t); + if (tmp == NULL) { + complain(t); + return t; + } + tm = *tmp; if (delta(&tm, &lotm) == (t - lot) && tm.tm_isdst == lotm.tm_isdst && strcmp(abbr(&tm), loab) == 0) { @@ -334,6 +362,14 @@ return result; } +static char * +nonnull_asctime(t) +const struct tm * t; +{ + static char null[] = "NULL"; + return (t == NULL) ? null : asctime(t); +} + static void show(zone, t, v) char * zone; @@ -344,12 +380,12 @@ (void) printf("%-*s ", (int) longest, zone); if (v) - (void) printf("%.24s UTC = ", asctime(gmtime(&t))); + (void) printf("%.24s UTC = ", nonnull_asctime(gmtime(&t))); tmp = localtime(&t); - (void) printf("%.24s", asctime(tmp)); - if (*abbr(tmp) != '\0') + (void) printf("%.24s", nonnull_asctime(tmp)); + if (tmp != NULL && *abbr(tmp) != '\0') (void) printf(" %s", abbr(tmp)); - if (v) { + if (tmp != NULL && v) { (void) printf(" isdst=%d", tmp->tm_isdst); #ifdef TM_GMTOFF (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); @@ -358,6 +394,13 @@ (void) printf("\n"); } +static void +complain(t) +time_t t; +{ + (void) printf("localtime() failed on input %lld\n", (long long)t); /*XXX*/ +} + static char * abbr(tmp) struct tm * tmp;