Bug 238547 - gmtime does not return NULL if the input cannot be represented as struct tm
Summary: gmtime does not return NULL if the input cannot be represented as struct tm
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: standards (show other bugs)
Version: 12.0-RELEASE
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-standards mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-06-13 18:30 UTC by Uri Simchoni
Modified: 2019-06-13 21:31 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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 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.