bug-gnulib
[Top][All Lists]
Advanced

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

Re: mktime() hangs for dates before 1970


From: Benjamin Lindner
Subject: Re: mktime() hangs for dates before 1970
Date: Fri, 28 Jan 2011 13:26:48 +0100

> Can you debug the problem, by seeing where the
> loop is in the mktime executable?  mktime.c has
> code to detect loops (look for the comment that
> mentions "oscillating") but evidently it is not
> working in your environment.

I stepped through the executable once for 1970-01-01 01:00:00 (which
works) and once for 1970-01-01 00:59:59 (which doesn't) and found that
the infinite loop occurres in the while loop in ranged_convert(), with
the steps towards there are as follows:

in __mktime_internal:344, t0 is calculated as 3599.
then proceeding to the for loop at line 407
in ranged_convert( t = 3599, tp = uninitialized)
   the call to convert(t = 3599, tm = uninitialized) returns r =
(59/59/1/1/0/70/4/0/0) which in turn is returned and passed on to
guess_time_tm( year=70, yday=0, hour=0, min=59, sec=59, t=3599, tp =
(59/59/1/1/0/70/4/0/0) )
  which calculates d as -3600 (which is correct) and sets t1 to -1,
and returns -1,

which is now assigned to gt, where the comparison between t (3599) and
gt (-1) fails, thus remaining_probes is decremented (now 5), and for
the next iteration, t is -1, gt is -1,

in ranged_convert( t = -1, tp = (59/59/1/1/0/70/4/0/0) )
   the call to convert( t = -1, tp = 59/59/1/1/0/70/4/0/0) ) returns r
= 0 (NULL), because localtime(-1) returns NULL,
   so now it enters the if {} statement in line 239, with bad = -1,
and ok = 0, but does not execute the while loop, because bad and ok
differ by 1 abolutely, so a value of NULL is returned and passed to
guess_time_tm( year=70, yday=0, hour=0, min=59, sec=59, t=-1, tp =
NULL ), which now does not exeute the if{} statement, but instead
returns -2^31 (i.e. TIME_T_MIN)...

... which is assigned to gt, where the comparison between t (-1) and
gt (-2^31) fails, thus remaining_probes is decremented (now 4), and
for the next iteration, t is -2^31, and gt is -2^31

in ranged_convert( t = -2^31, tp = (59/59/1/1/0/70/4/0/0) )
   the call to convert (t = -2^31, tp = (59/59/1/1/0/70/4/0/0) )
returns r = 0 (NULL)
   so it again enters the if {} statement, with bad = -2^31, and ok =
0. Now the while loop is executed and yields
      t = mid = +2^30, now the call to convert succeeds with r =
(4/37/14/10/0/104/6/9/0), so ok = 2^30
   next iteration of the while loop (ok = +2^30, bad = -2^31) yields t
= mid = 2^30+2^29, ...
   and this continues, until mid is filled with ones, i.e. mid = 2^31
- 1, and then loops infinitely, because mid no longer changes (it's
all bits 1)

so it looks like the binary search overflows in its calculations when
starting with TIME_T_MIN, because I guess that with bad=-2^31 and
ok=0, mid should be -2^30 in the next iteration, not +2^30.

benjamin



reply via email to

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