Report information
The Basics
Id:
46039
Status:
resolved
Priority:
Medium/Medium
Queue:

People
Owner:
Nobody in particular
Cc:
AdminCc:

BugTracker
Version Fixed:
9.9.12, 9.9.12(sub), 9.10.7, 9.10.7(sub), 9.11.3, 9.12.0
Version Found:
(no value)
Versions Affected:
(no value)
Versions Planned:
(no value)
Priority:
P2 Normal
Severity:
S2 Normal
CVSS Score:
(no value)
CVE ID:
(no value)
Component:
(no value)
Area:
(no value)

Dates
Created:Tue, 19 Sep 2017 04:36:16 -0400
Updated:Tue, 26 Sep 2017 20:18:39 -0400
Closed:Tue, 26 Sep 2017 20:18:38 -0400



This bug tracker is no longer active.

Please go to our Gitlab to submit issues (both feature requests and bug reports) for active projects maintained by Internet Systems Consortium (ISC).

Due to security and confidentiality requirements, full access is limited to the primary maintainers.

Date: Tue, 19 Sep 2017 16:35:48 +0800
Subject: strftime is not very platform neutral
From: "张杰" <zj@wangsu.com>
To: bind-bugs@isc.org

I think I encounter a problem when using the DIG command on the WINDOWS system, the command output contains some bytes which cannot be encoded in any formats, it should be either the time-zone name or time zone abbreviation, depending on registry settings.

My operating system is Windows with Chinese language package, time zone is the Chinese Standard Time.

My analysis of the code is as follows:

In the corresponding source code for the DIG program (BIND-9.11.2) dig.c Line 260, the library function strftime () is used.

 

if (strftime(time_str, sizeof(time_str),

             "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)

        printf(";; WHEN: %s\n", time_str);

 

It normally works fine, but on the Windows system with Chinese language package, it is not very platform neutral, the strftime function cannot get the correct time zone name by formatting the parameter %Z.

The time zone name is usually changed depending on the environment variable $TZ, but current systems don't use $TZ variable for any common purpose now. Nowadays, Linux / BSD make use of zoneinfo database which automatically handles GMT offset and DST, and $TZ can also be optionally set to location of these zoneinfo files under /usr/share/zoneinfo to override system setting. In my environment, the time zone name is CST (China Standard Time), written in English.

But the situation on Windows is different, the time zone name will change according to the settings of Control Panel. In my environment, Chinese characters is obtained:  

In order to store the Chinese character encoding information correctly, you must use the wcsftime function rather than strftime, and set the first parameter type wchar_t * rather than char * . wcsftime is the wide-character equivalent of strftime; its string-pointer argument points to a wide-character string. strftime cannot return the correct encoding bytes, leading to the final output displaying Chinese characters incorrectly , because the bytes returned do not match any character encoding formats.

Interestingly, if you directly use the char * string copied from the _tzname structure, it shows Chinese characters correctly.

 

Here is my example code to debug on Windows and the output:

// strftime example

 

#include <stdio.h>      // printf

#include <time.h>       // time_t, struct tm, time, localtime, strftime

#include <string.h>    // strcpy

 

int main()

{

    time_t rawtime;

    struct tm * timeinfo;

    char buffer1[80];

    wchar_t wide_char_buffer[80];

    char buffer2[80];

 

    time(&rawtime);

    timeinfo = localtime(&rawtime);

 

    wcsftime(wide_char_buffer, 80, L"%Z", timeinfo); 

    strftime(buffer1, 80, "%Z", timeinfo); 

    printf("%ls\n", wide_char_buffer);   // output is OK, we got China Standard Time in Chinese

    printf ("%s\n", buffer1);              // output is abnormal, cannot recognize time zone information

 

    strcpy(buffer2, _tzname[0]);       

    printf("%s\n", buffer2);               // output is also OK

    return 0;

}


Image displayed inline above

Image displayed inline above

Image displayed inline above

Subject: Re: [ISC-Bugs #46039] strftime is not very platform neutral
Date: Tue, 19 Sep 2017 19:15:38 +1000
From: "Mark Andrews" <marka@isc.org>
To: bind9-confidential@isc.org
Does this work for you? diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 562ef79a73..f67f1080df 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -231,7 +231,11 @@ received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { isc_uint64_t diff; time_t tnow; struct tm tmnow; +#ifdef WIN32 + wchar_t time_str[100]; +#else char time_str[100]; +#endif char fromtext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(from, fromtext, sizeof(fromtext)); @@ -250,9 +254,15 @@ received(int bytes, isc_sockaddr_t *from, dig_query_t *query) { tmnow = *localtime(&tnow); #endif +#ifdef WIN32 + if (wcsftime(time_str, sizeof(time_str)/sizeof(time_str[0]), + "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) + printf(";; WHEN: %ls\n", time_str); +#else if (strftime(time_str, sizeof(time_str), "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U) printf(";; WHEN: %s\n", time_str); +#endif if (query->lookup->doing_xfr) { printf(";; XFR size: %u records (messages %u, " "bytes %" ISC_PRINT_QUADFORMAT "u)\n", -- Mark Andrews, ISC 1 Seymour St., Dundas Valley, NSW 2117, Australia PHONE: +61 2 9871 4742 INTERNET: marka@isc.org
ready for review
Added a comment explaining why wcsftime() is used. Looks good otherwise.
4738. [port] win32: strftime mishandles %Z. [RT #46039]