| |
|
Nick
Posted in reply to Manfred Nowak
| In article <d4aqf3$2c5p$1@digitaldaemon.com>, Manfred Nowak says...
>
><code>
>import std.date, std.stdio;
>
>void main(){
> static int times[3]=[
> -61367296,
> -36334592,
> -11301888]
> ;
>
> d_time t= parse("1 1 1970");
> for( int i= 0; i < 3; i++){
> toString( t + times[ i]);
> }
>
>
>}
></code>
I took the time to track this one down for you. The hang occers in std.date.toString() when called with a very large argument. It can be traced to the function YearFromTime in date.d:
# int YearFromTime(d_time t)
# { int y;
#
# // Hazard a guess
# y = 1970 + cast(int) (t / (365.2425 * msPerDay));
#
# if (TimeFromYear(y) <= t)
# {
# while (TimeFromYear(y + 1) <= t)
# y++;
# }
# else
# {
# do
# {
# y--;
# }
# while (TimeFromYear(y) > t);
# }
# return y;
# }
There are two problems here. First, TimeFromYear takes an int as an argument, and passes it to DayFromYear, which both takes and returns ints. With sufficiently large parameters this calculation will overflow. But this can be considered reasonable, since years are not expected to be this big.
Second, the time parameter you pass to toString is large enough that
TimeFromYear(y+1) overflows but TimeFromYear(y) does not (even when all
calculations are changed to use longs.) This causes the first while loop to run
indefinitely.
In all the test I ran (that didn't overflow, ie. with reasonable parameters), the loop count for the while/do-while loops were at most one, and mostly zero. I therefore think it's reasonably safe to add some overflow checks, ie. something like:
# int count;
[...]
# while (TimeFromYear(y + 1) <= t)
# {
# if(count++ > 10) throw new Exception("Date overflow");
# y++;
# }
Nick
|