[PATCH] libc/time/gmtime_r.c (gmtime_r): Fixed bug in calculations for dates after year 2069 or before year 1901

Freddie Chopin freddie_chopin@op.pl
Sun Dec 7 18:34:00 GMT 2014


It turns out that the implementation of gmtime_r() with my modifications 
from September has a bug... The problem with this bug is that it shows 
only for dates after 2069 or before 1901, so to actually experience this 
bug time_t must be 64-bits long (or 32-bit unsigned, but I don't think 
such combination exists for any platform). The root cause of the problem 
is that the assumptions that there are 97 leap years in 400-year periods 
and 24 leap years in 100-year periods are valid only if you consider 
"full cycles". So there are 97 leap years between 2000 and 2400, or 24 
leap years between 2000 and 2100, but _NOT_ between 1970 and 2070... The 
fix is to move the epoch from 1st January 1970 to 1st March of 2000 
(beginning of 400-year cycle, right after additional day of leap year - 
29th February 2000), perform the calculations and adjust back at the end.

Attached patch implements this fix. The solution was tested by comparing 
the produced value with gmtime_r() from GLIBC for every hour in 
1602-year period (years 1399 - 2801, inclusive).

The idea for solution comes from implementation of the same 
functionality in musl library, which used almost the same idea that I 
used initially (that was a coincidence).

Unfortunatelly on ARM Cortex-M3 platform these modifications make the 
function run twice as long as previously (2M iterations take 29s vs 15s 
on a 16MHz clock)... I'm not really sure how is that possible (the 
changes don't look that heavy), but that's the reality... As a possible 
optimization, quite a lot of the code can be removed for platforms where 
time_t is 32-bit long, but that's another thing.

BTW - are there any platforms which have time_t as a 64-bit variable 
that use newlib, that would be affected by this problem?

-------------- next part --------------
A non-text attachment was scrubbed...
Name: libc-time-gmtimerc-gmtimer-Fixed-bug-in-calculations.patch
Type: text/x-patch
Size: 6127 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20141207/91a7bda7/attachment.bin>
-------------- next part --------------
2014-12-07  Freddie Chopin  <freddie_chopin@op.pl>

	* libc/time/gmtime_r.c (gmtime_r): Fixed bug in calculations for dates
	after year 2069 or before year 1901. Ideas for solution taken from
	musl's __secs_to_tm()

More information about the Newlib mailing list