This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Invalid tm_zone from localtime() when TZ is not set


On Fri, May 20, 2016 at 6:22 AM, KOBAYASHI Shinji  wrote:
(snip)
>
> localtime() calls tzsetwall() when TZ is not set. In tzsetwall(),
> the StandardName and DaylightName member values retrieved by
> GetTimeZoneInformation() are checked with isupper() and copied to the
> char[] buffer used as the timezone name in tzparse(). However, the
> type of these member values are wchar_t and isupper() is defined only
> when isascii() is true.

If the type of those members is WCHAR[] then using isascii() /
isupper() on them is just plain wrong.
The correct function to use would be iswupper().

The line
    if (isupper(*src)) *dst++ = *src;

(where src is wchar_t* and dst is char*) assumes that the upper 8 bits
of *src are zero (or *src is -1).
If not, the behavior is at best implementation-defined (maybe even undefined).

> So it may happen that the char[] buffer
> contains invalid characters as a result of implicit cast from wchar_t
> to char.
>
> The return value of isupper() for non-ascii characters depends on
> other data, because an out of bounds access occurs for the small
> (128 + 256) table used in isupper(). I confirmed the above error on
> Japanese Windows with 64-bit Cygwin 2.5.0-1 and 2.5.1-1, but had no
> problem with 64-bit Cygwin 2.4.1-1 nor with 32-bit Cygwins.
>
> So, I propose to call isascii() to assure the wchar_t fits in the
> range of ASCII before calling isupper().
>
> I have considered some other methods:
>
> 1. Using iswupper() instead of isupper().
>    - Although this method is effective for Japanese environments, it
>      is not assured that the character iswupper() returns true fits in
>      the range of ASCII.

It is highly likely that if the argument of iswupper() does not fit
into ASCII then its result won't fit either.

> 2. Add (char) cast to the argument of isupper().
>    - This method assures that the copied characters are uppercase
>      only. However, it may be different from original characters due
>      to casting.
>



-- 
GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++
The Tao of math: The numbers you can count are not the real numbers.
Life is complex, with real and imaginary parts.
"Ok, it boots. Which means it must be bug-free and perfect. " -- Linus Torvalds
"People disagree with me. I just ignore them." -- Linus Torvalds

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]