Bug 238547

Summary: gmtime does not return NULL if the input cannot be represented as struct tm
Product: Base System Reporter: Uri Simchoni <urisimchoni>
Component: standardsAssignee: freebsd-standards (Nobody) <standards>
Status: New ---    
Severity: Affects Some People CC: kib
Priority: ---    
Version: 12.0-RELEASE   
Hardware: Any   
OS: Any   

Description Uri Simchoni 2019-06-13 18:30:49 UTC
When the input to gmtime() represents a time that's too far in the future, and whose year does not fit in the tm_year field, gmtime() returns a struct tm with all-zeros.

Contrast this with POSIX (https://pubs.opengroup.org/onlinepubs/009695399/functions/gmtime.html) which states that in this case the return should be NULL with errno set to reflect the error. Other libc's (glibc, MacOS, MSVC) also return NULL in this case.

For example,

time_t val = 0x7fffffffffffffffll;
gmtime(&val)

does not return NULL.

This affects my ability to correctly calculate the maximum allowed value of time_t in Samba's configure phase.

Thanks,
Uri.
Comment 1 Uri Simchoni 2019-06-13 19:27:37 UTC
Correction - if the input cannot be represented as struct tm, gmtime returns whatever's in it's internal struct tm, and does not even set errno.

For example:

#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

int main()
{
    time_t max_time = 0x7fffffffffffffffll;
    int e;
    errno = 0;
    tm = gmtime(&max_time);
    e = errno;
    printf("gmtime(0x7fffffffffffffffll) == %stm_year = %d errno = %d\n\n", asctime(tm), tm->tm_year, e);
    max_time = 60000000000000000ll;
    errno = 0;
    tm = gmtime(&max_time);
    e = errno;
    printf("gmtime(60000000000000000ll) == %stm_year = %d errno = %d\n\n", asctime(tm), tm->tm_year, e);
    max_time = 0x7fffffffffffffffll;
    errno = 0;
    tm = gmtime(&max_time);
    e = errno;
    printf("gmtime(0x7fffffffffffffffll) == %stm_year = %d errno = %d\n", asctime(tm), tm->tm_year, e);
    return 0;
}

Yields the following output:
gmtime(0x7fffffffffffffffll) == Sun Jan  0 00:00:00 1900
tm_year = 0 errno = 0

gmtime(60000000000000000ll) == Sat May 29 10:40:00     1901326280
tm_year = 1901324380 errno = 0

gmtime(0x7fffffffffffffffll) == Sat May 29 10:40:00     1901326280
tm_year = 1901324380 errno = 0
Comment 2 Konstantin Belousov freebsd_committer freebsd_triage 2019-06-13 21:31:46 UTC
Your issue should be handled by https://reviews.freebsd.org/D20631, but there is at least one test failure with the patch applied.  It seems to break t_mktime:timegm_epoch.

I am not sure where is a cause of the failure, in my patch, or is there one more bug in tzcode.