zdump -v crashes with 64-bit time_t

Paul Eggert eggert at CS.UCLA.EDU
Thu Jun 17 21:16:16 UTC 2004


"Olson, Arthur David (NIH/NCI)" <olsona at dc37a.nci.nih.gov> writes:

> It might be better to cut off at something such as...
> 	2050 + 100 * ((current_year - 1930) / 100)
> ...to ease regression testing

Good point; here's a further patch to implement this.  I fixed a
couple of other minor problems with outlandishly large years that I
noticed while composing this change.

===================================================================
RCS file: RCS/zdump.8,v
retrieving revision 2004.1.0.1
retrieving revision 2004.1.0.2
diff -pc -r2004.1.0.1 -r2004.1.0.2
*** zdump.8	2004/06/15 05:24:21	2004.1.0.1
--- zdump.8	2004/06/17 21:10:14	2004.1.0.2
*************** otherwise.
*** 40,46 ****
  .TP
  .BI "\-c " cutoffyear
  Cut off the verbose output near the start of the given year.
! By default, verbose output is cut off approximately 50 years after the
  current date and time.
  .SH "SEE ALSO"
  newctime(3), tzfile(5), zic(8)
--- 40,46 ----
  .TP
  .BI "\-c " cutoffyear
  Cut off the verbose output near the start of the given year.
! By default, verbose output is cut off a few decades after the
  current date and time.
  .SH "SEE ALSO"
  newctime(3), tzfile(5), zic(8)
===================================================================
RCS file: RCS/zdump.c,v
retrieving revision 2003.3.0.2
retrieving revision 2003.3.0.4
diff -pc -r2003.3.0.2 -r2003.3.0.4
*** zdump.c	2004/06/15 05:24:21	2003.3.0.2
--- zdump.c	2004/06/17 21:12:39	2003.3.0.4
*************** char *	argv[];
*** 170,176 ****
  	register int		c;
  	register int		vflag;
  	register char *		cutoff;
! 	register int		cutyear;
  	register time_t		lasttime;
  	char **			fakeenv;
  	time_t			now;
--- 170,177 ----
  	register int		c;
  	register int		vflag;
  	register char *		cutoff;
! 	register long		cutyear;
! 	long			y;
  	register time_t		lasttime;
  	char **			fakeenv;
  	time_t			now;
*************** _("%s: usage is %s [ --version ] [ -v ] 
*** 216,241 ****
  	time_t_min = TYPE_SIGNED(time_t) ? hibit : 0;
  	(void) time(&now);
  	if (cutoff != NULL) {
! 		int	y;
! 
! 		cutyear = atoi(cutoff);
! 		lasttime = 0;
! 		for (y = EPOCH_YEAR; y < cutyear; ++y)
! 			lasttime += DAYSPERNYEAR + isleap(y);
! 		lasttime *= SECSPERHOUR * HOURSPERDAY;
! 		lasttime -= TYPE_SIGNED(time_t) || lasttime != 0;
  	} else {
  		/*
  		** By default, the cutoff is the maximum time value,
! 		** or about 50 years from now, whichever comes first.
  		** This prevents us from generating too much output if
! 		** time_t is 64 bits.  31556952 is 365.2425 * 24 * 60
! 		** * 60, but don't trust the C compiler to calculate
! 		** it as there may be bugs or rounding problems.
  		*/
! 		long seconds_per_mean_gregorian_year = 31556952;
! 		time_t now50 = now + 50 * seconds_per_mean_gregorian_year - 1;
! 		lasttime = now < now50 ? now50 : time_t_max;
  	}
  	longest = 0;
  	for (i = optind; i < argc; ++i)
--- 217,247 ----
  	time_t_min = TYPE_SIGNED(time_t) ? hibit : 0;
  	(void) time(&now);
  	if (cutoff != NULL) {
! 		cutyear = atol(cutoff);
  	} else {
  		/*
  		** By default, the cutoff is the maximum time value,
! 		** or a few decades from now, whichever comes first.
  		** This prevents us from generating too much output if
! 		** time_t is wider than 32 bits.
  		*/
! 		newtm = gmtime (&now);
! 		if (newtm == NULL)
! 			cutyear = now < 0 ? LONG_MIN : LONG_MAX;
! 		else {
! 			cutyear = newtm->tm_year + (long) TM_YEAR_BASE;
! 			cutyear = 2050 + 100 * ((cutyear - 1930) / 100);
! 		}
! 	}
! 	lasttime = 0;
! 	for (y = EPOCH_YEAR; y < cutyear; ++y) {
! 		newt = lasttime - !lasttime;
! 		newt += (DAYSPERNYEAR + isleap(y)) * SECSPERHOUR * HOURSPERDAY;
! 		if (newt < lasttime) {
! 			lasttime = time_t_max;
! 			break;
! 		}
! 		lasttime = newt;
  	}
  	longest = 0;
  	for (i = optind; i < argc; ++i)



More information about the tz mailing list