Ticket #37938

Conflicts in time_t type definition between MSVCRT.DLL, UCRTBASE.DLL, and VC++ non-free runtimes

오픈 날짜: 2018-02-04 03:05 마지막 업데이트: 2018-03-06 07:00

Reporter:
소유자:
Type:
Status:
Open [Owner assigned]
Component:
MileStone:
(None)
Priority:
5 - Medium
Severity:
5 - Medium
Resolution:
None
File:
4
Vote
Score: 0
No votes
0.0% (0/0)
0.0% (0/0)

Details

According to this Microsoft on-line documentation:

In versions of Visual C++ and Microsoft C/C++ before Visual C++ 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.

While this may be true, for applications which are built using Microsoft's Visual C++, (specifically from the 2005 version onward), and linked with the accompanying non-free versions of Microsoft's C-Runtime library, (from MSVCR80.DLL onward, and perhaps also with the pseudo-free UCRTBASE.DLL), it is manifestly untrue for applications which are linked with the pseudo-free MSVCRT.DLL, (the normal case for MinGW applications), as it is for applications which are built with, and linked with the C-Runtime libraries which accompanied, earlier (legacy) versions of Microsoft's Visual C++, (i.e. applications which are linked with Microsoft's non-free runtime libraries pre-dating MSVCR80.DLL).

We need to engineer a time management API which will accommodate the disparities between MSVCRT.DLL, UCRTBASE.DLL, and Microsoft's post-2005 Visual C++ implementations of various time management functions, and we must recognise that our API cannot blindly conform to the above paragraph from Microsoft's current documentation.

Ticket History (3/12 Histories)

2018-02-04 03:05 Updated by: keith
  • New Ticket "Conflicts in time_t type definition between MSVCRT.DLL, UCRTBASE.DLL, and VC++ non-free runtimes" created
2018-02-05 06:33 Updated by: earnie
  • Details Updated
댓글 올리기

And what we engineer should not interfere with someone compiling the code with Visual C++ which must "blindly conform" to that documentation. The engineering needs to use the versioning macros to determine what the default for time_t is. Any missing element in MSVCRT.DLL or UCRTBASE.DLL needs to be managed with a MinGW specific element which mimics the MS elements.

2018-02-11 02:37 Updated by: keith
댓글 올리기

Reply To earnie

I do not appreciate the antagonistic tone of your comment; neither do I appreciate your apparent underhand attempt to resurrect, in public, a private disagreement which I thought we had put behind us.

And what we engineer should not interfere with someone compiling the code with Visual C++ which must "blindly conform" to that documentation.

Of course, but how on earth could any such engineering in any way impact users of Visual C++? They will be using Microsoft's headers and implementations; for them, our engineering is irrelevant.

The engineering needs to use the versioning macros to determine what the default for time_t is.

And this is exactly what my existing implementations do, for 32-bit Windows; the purpose of this ticket is to invite pragmatic discussion of what further changes, if any, may be required to support 64-bit Windows.

Any missing element in MSVCRT.DLL ...

There are no missing elements, among the generically named time_t dependent functions, from any version of MSVCRT.DLL. The omissions are the 64-bit time_t explicit overrides, prior to Win2K, and 32-bit explicit "overrides", (on 32-bit Windows, MSVCRT.DLL's generically named implementations unequivocally represent time_t as a 32-bit entity), prior to Vista.

... or UCRTBASE.DLL needs to be managed with a MinGW specific element which mimics the MS elements.

UCRTBASE.DLL appears to exhibit the same limitations as MSVCR80.DLL, and its successors; all generically named function implementations are missing, and all must be emulated by in-line redirection within header files. Once again, I already have implementations which do this for 32-bit Windows; this ticket needs only to identify any changes which may be needed to support 64-bit Windows.

(Edited, 2018-02-11 02:39 Updated by: keith)
2018-02-11 06:32 Updated by: keith
댓글 올리기

Fundamentally, this issue revolves around the implementations of the following 13 generically named functions:

ctime
difftime
_ftime
_futime
gmtime
localtime
_mkgmtime
mktime
time
utime
_utime
_wctime
_wutime

Every one of these is physically implemented within, and exported by, MSVCRT.DLL, (both 32-bit and 64-bit versions, AFAICT). None of them are physically present within UCRTBASE.DLL, nor in MSVCR80.DLL, (nor in any of its successors); each is provided by in-line redirection, to either a 32-bit or 64-bit time_t specific equivalents, as specified within appropriate header files, and as directed by user specification, or otherwise, of the _USE_32BIT_TIME_T feature test.

On the 32-bit Windows platform, the attached chktime.c program unequivocally demonstrates that, in the case of the time() function, the MSVCRT.DLL implementation always interprets time_t as a 32-bit entity, irrespective of whether _USE_32BIT_TIME_T is defined or not. On 64-bit Windows it may become a 64-bit entity, but I do not have a platform on which I can test this; thus, I would appreciate if someone with a suitable platform, could, as the first step in a pragmatic investigation, compile chktime.c as a 64-bit application, run it, and attach its output here.

(Edited, 2018-02-13 04:33 Updated by: keith)
2018-02-11 07:01 Updated by: keith
댓글 올리기

For the record, the output from chkime.c, after compiling it, and running it on 32-bit WinXP-SP2, is:

$ /e/chktime
Seconds elapsed since the beginning of the unix epoch,
as reported by MSVCRT.DLL time functions with time_t interpreted as:--

             Uninterpreted [*]   32-bit (__time32_t)   64-bit (__time64_t)
            ------------------  --------------------  --------------------
    time(): 0xaaaaaaaa5a7f4a1e           +1518291486  -6148914692581537250
 _time32():                 *** function not supported ***
 _time64(): 0x000000005a7f4a1e           +1518291486           +1518291486
 ---------  ------------------  --------------------  --------------------

[*] This is a hexadecimal representation of the content of the 64-bit
    results buffer, AFTER the function call; note that this was filled
    with 0xaa bytes BEFORE the function call, and that any bytes which
    retain this value after the call may be assumed to have remained
    untouched, when calling the specified function.

As can clearly be seen, attempting to interpret the time_t value returned by the generic time() function, as a 64-bit entity, (as the Microsoft documentation would have us believe it should be), results in complete garbage!

2018-02-11 07:35 Updated by: keith
댓글 올리기

A further example, running pre-compiled chktime.c on 32-bit Win7:

$ /e/chktime
Seconds elapsed since the beginning of the unix epoch,
as reported by MSVCRT.DLL time functions with time_t interpreted as:--

             Uninterpreted [*]   32-bit (__time32_t)   64-bit (__time64_t)
            ------------------  --------------------  --------------------
    time(): 0xaaaaaaaa5a7f6e66           +1518300774  -6148914692581527962
 _time32(): 0xaaaaaaaa5a7f6e66           +1518300774  -6148914692581527962
 _time64(): 0x000000005a7f6e66           +1518300774           +1518300774
 ---------  ------------------  --------------------  --------------------

[*] This is a hexadecimal representation of the content of the 64-bit
    results buffer, AFTER the function call; note that this was filled
    with 0xaa bytes BEFORE the function call, and that any bytes which
    retain this value after the call may be assumed to have remained
    untouched, when calling the specified function.

In this case, we can clearly see that time() and _time32(), (which is supported on this platform), return identical results. Once again, time_t is unequivocally interpreted as 32-bit, regardless of _USE_32BIT_TIME_T remaining unspecified, for both of these functions; any attempt to interpret it as 64-bit again results in garbage.

The only way to have time_t interpreted as 64-bit, when using 32-bit MSVCRT.DLL, is to call _time64() explicitly, and that isn't supported on any Windows version prior to Win2K. Attempting to emulate Microsoft's documented _USE_32BIT_TIME_T behaviour, when using MSVCRT.DLL will break legacy support for 32-bit pre-Win2K; from my POV, that is not an acceptable solution.

2018-02-25 03:44 Updated by: keith
댓글 올리기

Back in 2016, I refactored several of the mingwrt headers, to ensure that various time_t dependent data types and functions, (and indeed time_t itself), are correctly declared, or defined, for the various usage cases which may arise on 32-bit Windows. At that time, I neglected to address the sets of such type definitions, and function declarations, which appear in the <sys/utime.h> (Microsoft's preferred equivalent of POSIX.1's <utime.h>), and <sys/timeb.h> header files.

These omissions are now addressed, respectively, by the attached sys-utime-header.patch and sys-timeb-header.patch patch files, (which I've already committed to the WSL repository).

(Edited, 2018-03-06 07:01 Updated by: keith)
2018-03-06 07:00 Updated by: keith
댓글 올리기

A related issue arises, in connection with the GetAdaptersInfo() API, as implemented within iphlpapi.dll ... specifically within the IP_ADAPTERS_INFO structural data type, (defined in <iptypes.h>), which is used to retrieve the adapters info. As documented by Microsoft, each entry in this structured array includes a pair of time_t fields; in reality, on 32-bit Windows, the iphlpapi.dll implementation requires each of these to be defined as the equivalent of __time32_t fields.

Microsoft's suggested work-around for this anomaly is to require users to specify _USE_32BIT_TIME_T within any translation unit, compiled for 32-bit Windows, in which the IP_ADAPTERS_INFO data type is referenced. This is abysmally poor systems engineering; users should not have to contend with such nonsense! The attached iptypes-self-contained.patch corrects this, in a completely deterministic fashion which does not require such user intervention, while simultaneously ensuring that <iptypes.h> may be included without imposing, on users, the onus for resolving its additional header file dependencies.

(This iptypes-self-contained.patch has already been committed to the WSL repository, and incorporated into the w32api-5.1 release).

(Edited, 2018-03-07 03:08 Updated by: keith)

Edit

Please login to add comment to this ticket » Login