zdump -v crashes with 64-bit time_t
Ken Pizzini
tz. at explicate.org
Tue Jun 15 04:30:09 UTC 2004
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;
More information about the tz
mailing list