bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: time_t on NetBSD/i386


From: Paul Eggert
Subject: Re: time_t on NetBSD/i386
Date: Thu, 17 Sep 2009 16:39:50 -0700
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.2 (gnu/linux)

Bruno Haible <address@hidden> writes:

> Yes. The naming of the variable 'long_int_year_and_yday_are_wide_enough'
> sounds as if Paul intended to be able to pass time_t values into 'year1'
> and 'yday1'. But this does not happen: all inputs are 'int'.

Sorry about the long delay.  It's been many years, but I think the
problem is partly in this line:

  time_t years = tyear1 - year0;

Here tyear1 is of type time_t, copied from a long int value, and year0
is of type int.  The long int's absolute value cannot possibly be
greater than approximately INT_MAX + INT_MAX/12.

Now, where did that INT_MAX + INT_MAX/12 come from?  From this
(faraway) line:

  long int year = lyear_requested + mon_years;

If memory serves, the problem is that if either the addition or the
subtraction overflows, it can overflow in such a bad way that the rest
of the code (which attempts to do overflow checking) won't detect the
error.  If my memory is right, we have two rules: (a) If the addition
can't possibly overflow, it's not a problem.  Also, (b) if time_t is a
sufficiently narrow type, it's not a problem: the bad overflow cannot
screw up so badly that the overall overflow won't be detected.  Hence
the assertion:

  verify (long_int_year_and_yday_are_wide_enough,
          INT_MAX <= LONG_MAX / 2 || TIME_T_MAX <= UINT_MAX);

The two halves of the disjunct are attempting to check the two rules
(a) and (b) mentioned above.

I can't say I ever _tested_ this: I was just trying to throw in a
compile-time check saying "whoa! if you're on that weird a host you'd
better know what you're doing!"

Since we've found a host where these assumptions aren't true any more,
we should bulletproof the running code so that it'll work correctly on
the host.  Clearly that addition "can" overflow on NetBSD.

One possible workaround is to replace all instances of "long int" with
"intmax_t".  I couldn't reliably do that back when I wrote this code
because I couldn't rely on intmax_t.

By the way, all this complication is needed because it isn't correct
to put in overflow checking after each individual addition,
subtraction, or multiplication, because that will incorrectly report
some overflows even though there's a well-defined and correct answer
that is computed by wraparound overflow.

(end of trip down memory lane)

All of the above discussion assumes integer overflow wraps around
reliably.  Since that assumption is becoming less and less true,
perhaps the code should be rewritten more drastically.  That'd be a
bigger project though.  My vague impression is that GCC and other
compilers are not likely to be smart enough to generate code that will
break mktime.c, so I haven't worried about this so far.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]