Обсуждение: Y2038 BUG

Поиск
Список
Период
Сортировка

Y2038 BUG

От
Bryan Green
Дата:
Hello,

There is a Y2038 bug in win32gettimeofday.c due to long being 32-bits on
Windows and the use of struct timeval.

int
gettimeofday(struct timeval *tp, void *tzp)


struct timeval is defined in winsock2.h and is needed by the Windows
select() call. The 64-bit values have to be narrowed to 32-bit values
for the struct timeval slots.

tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC);

tp->tv_usec = (long) (((ularge.QuadPart - epoch) %
FILETIME_UNITS_PER_SEC) / FILETIME_UNITS_PER_USEC);


I set my system clock to be in 2038 you can see the "wrap-around" error
in the following test.

C:\pg99>date 01-19-2038

C:\pg99>bin\psql -d postgres -p 5454 -c "SELECT clock_timestamp(),
extract(epoch from clock_timestamp()), timeofday();"
        clock_timestamp        |      extract       |              timeofday
-------------------------------+--------------------+-------------------------------------
 1901-12-13 18:46:42.483928-06 | -2147469197.516072 | Fri Dec 13
18:46:42.484319 1901 CST
(1 row)

I then set it to a date before 2038 but still in the future and it
worked as expected.

C:\pg99>date 05-19-2035

C:\pg99>bin\psql -d postgres -p 5454 -c "SELECT clock_timestamp(),
extract(epoch from clock_timestamp()), timeofday();"
        clock_timestamp        |      extract      |              timeofday
-------------------------------+-------------------+-------------------------------------
 2035-05-19 02:15:09.119002-05 | 2063171709.119002 | Sat May 19
02:15:09.119315 2035 CDT
(1 row)

The struct timeval is unguarded in winsock2.h are we could just use the
guard to define our own.

We can create our own pg_timeval with a few helper conversion functions.
 Obviously, there are a lot of places in the codebase where gettimeofday
is called.  My question is whether we want to fix this now or wait with
crossed fingers that Microsoft fixes this in a timely manner?

If we choose to create our own timeval struct, should we convert to
struct timespec instead?  If we want to move forward with either of
these for a Y2038 fix, I will be more than happy to create a patch for
whichever.

Bryan Green





Re: Y2038 BUG

От
Tom Lane
Дата:
Bryan Green <dbryan.green@gmail.com> writes:
> There is a Y2038 bug in win32gettimeofday.c due to long being 32-bits on
> Windows and the use of struct timeval.

Yeah.

>  Obviously, there are a lot of places in the codebase where gettimeofday
> is called.  My question is whether we want to fix this now or wait with
> crossed fingers that Microsoft fixes this in a timely manner?

I'm not sure how much we can do about this without knowing what they
and other platforms will do.  The one saving grace about this is that
we don't need a huge amount of advance notice, because we don't use
time_t and friends for any future timestamps, only current time.

> If we choose to create our own timeval struct, should we convert to
> struct timespec instead?

The bigger picture here is that POSIX defines both struct timeval
and struct timespec as using time_t, so on a platform that hasn't
widened time_t there is going to be a Y2038 issue no matter what.
struct timespec isn't going to help.

The last I heard about this (which was some time ago now) there
was some thought among libc maintainers that they might not take
the ABI break of widening time_t on 32-bit platforms, but instead
redefine the origin (time_t zero) every 70 years or so.  That would
actually be rather problematic for us because we need to know the
origin in order to convert clock readings into PG timestamps.

It would likely be a good idea to take steps to remove direct
dependence on time_t/timeval/timespec from as many places as possible,
so as to minimize the blast radius once platforms start to actually
deal with this issue.

It looks like we've allowed a lot of frontend code to avoid the
backend practice of working in Timestamp(Tz).  Maybe that's okay ---
assuming that that code is only interested in times near current
time --- but it's certainly something that could bite people on the
rear if they're careless about assumptions.

            regards, tom lane



Re: Y2038 BUG

От
Bryan Green
Дата:
On 11/2/2025 4:48 PM, Tom Lane wrote:
> Bryan Green <dbryan.green@gmail.com> writes:
>> There is a Y2038 bug in win32gettimeofday.c due to long being 32-bits on
>> Windows and the use of struct timeval.
> 
> Yeah.
> 
>>  Obviously, there are a lot of places in the codebase where gettimeofday
>> is called.  My question is whether we want to fix this now or wait with
>> crossed fingers that Microsoft fixes this in a timely manner?
> 
> I'm not sure how much we can do about this without knowing what they
> and other platforms will do.  The one saving grace about this is that
> we don't need a huge amount of advance notice, because we don't use
> time_t and friends for any future timestamps, only current time.
> 
>> If we choose to create our own timeval struct, should we convert to
>> struct timespec instead?
> 
> The bigger picture here is that POSIX defines both struct timeval
> and struct timespec as using time_t, so on a platform that hasn't
> widened time_t there is going to be a Y2038 issue no matter what.
> struct timespec isn't going to help.
> 

Microsoft now has a define for time_t that sets it to __time64_t.

In versions of Visual C++ and Microsoft C/C++ before Visual Studio 2005,
time_t was a long int (32 bits) and hence could not be used for dates
past 3:14:07 January 19, 2038, UTC. time_t is now equivalent to
__time64_t by default, but defining _USE_32BIT_TIME_T changes time_t to
__time32_t and forces many time functions to call versions that take the
32-bit time_t. For more information, see Standard types and comments in
the documentation for the individual time functions.
 ...per
https://learn.microsoft.com/en-us/cpp/c-runtime-library/time-management?view=msvc-170

timeval is still problematic on windows though...just available through
winsock2.h and uses long..not time_t.

> The last I heard about this (which was some time ago now) there
> was some thought among libc maintainers that they might not take
> the ABI break of widening time_t on 32-bit platforms, but instead
> redefine the origin (time_t zero) every 70 years or so.  That would
> actually be rather problematic for us because we need to know the
> origin in order to convert clock readings into PG timestamps.
> 
> It would likely be a good idea to take steps to remove direct
> dependence on time_t/timeval/timespec from as many places as possible,
> so as to minimize the blast radius once platforms start to actually
> deal with this issue.
> 

I agree. I will give this some thought.

> It looks like we've allowed a lot of frontend code to avoid the
> backend practice of working in Timestamp(Tz).  Maybe that's okay ---
> assuming that that code is only interested in times near current
> time --- but it's certainly something that could bite people on the
> rear if they're careless about assumptions.
> 
>             regards, tom lane

Yes, when I first saw this, I thought "oh, I can probably just handle
this with a new pg_timeval and only have to worry about
GetTimestampTZ...".

Bryan