core dump from within asctime_r()

Robert Elz kre at munnari.OZ.AU
Sat Jan 30 13:37:54 UTC 2010

A NetBSD user reported fsck dumping core (when attempting to
correct a corrupted filesystem).   That's not nice.

Upon investigation, the core dump turns out to be from within
asctime_r() (as called via asctime() from ctime()).

The code in fsck just does

	p = ctime(&t);

where "t" contains one of the time fields from an (already
determined to be corrupted, or we wouldn't be printing) inode.

ctime() is (or course) just asctime(locatime(t))

locatime() can return NULL these days, and given a nonsense time
value (which is quite likely under these circumstances), probably did,
but asctime() doesn't expect anything but a valus "struct tm *" and will
simply dereference NULL is NULL is returned from localtime() - instant core.

It would be possible to make ctime() be

	tm = localtime(t);
	if (tm == NULL)
		return NULL;
	return asctime(tm);

and in theory that would be adequate, but I'm actually going to suggest
moving the fix into asctime() (into asctime_r() really of course), and
have asctime_r() start

	if (timeptr == NULL)
		return NULL;

I think that's a safer fix.   Appended is the patch I suggest, made
against the tzcode2009t sources (latest I believe.)


-------------- next part --------------
--- asctime.c.was	2009-10-21 20:12:42.000000000 +0700
+++ asctime.c	2010-01-30 20:33:57.000000000 +0700
@@ -91,6 +91,10 @@
 	char			year[INT_STRLEN_MAXIMUM(int) + 2];
 	char			result[MAX_ASCTIME_BUF_SIZE];
+	if (timeptr == NULL) {
+		errno = EINVAL;
+		return NULL;
+	}
 	if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
 		wn = "???";
 	else	wn = wday_name[timeptr->tm_wday];

More information about the tz mailing list