mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Hannu Nyman <hannu.nyman@iki.fi>
To: musl@lists.openwall.com
Subject: Re: Bug in timezone handling (new zonename format like '<+04>-4' )
Date: Wed, 19 Oct 2016 09:40:18 +0300	[thread overview]
Message-ID: <f6468f7c-f322-ed8d-ab27-7afbd48138ea@iki.fi> (raw)
In-Reply-To: <699b8fe9-4693-8f71-c321-452c765f26a3@iki.fi>

Reference to earlier discussion in March 2016:
http://www.openwall.com/lists/musl/2016/03/31/10

I think that I have finally found the fix for the bug in handling <quoted> 
timezone names.

musl fails to parse timezone string if the zone name is defined in the quoted 
form with <>.
Example:
root@...nWrt:~# cat /etc/TZ
<+04>-4
root@...nWrt:~# date
Wed Mar 30 08:02:59 +04>-4 2016

(note that Openwrt/LEDE patches musl to use /etc/TZ instead of an environment 
variable, but that has no effect on the evaluation itself)

All new timezones & changes to old ones since zoneinfo 2016b seem to adopt 
the new way, and old zone name abbreviations (like EET) are being gradually 
removed. Currently already 47 timezones have numeric names inside < >. 
Examples of new timezone strings (after 2016g):
'Antarctica/Troll', '<+00>0<+02>-2,M3.5.0/1,M10.5.0/3'
'Asia/Baku', '<+04>-4'
'Europe/Istanbul', '<+03>-3'
'Europe/Minsk', '<+03>-3'

I think that I have now found the bug in musl and fixed it.

The core reason is a fault in the logic for quoted timezone names in function 
"getname" in __tz.c. The name string evaluation loop forgets to push the 
pointer forward to get the next character. The pointer "*p" is explicitly 
moved one char forward to skip the "<" (and afterwards for ">"), but during 
the actual name evaluation loop the same "*p" is used until "i" reaches 
TZNAME_MAX and breaks the loop. After the loop, at the end of the function 
"*p" is increased by the (wrongly detected) length. _POSIX_TZNAME_MAX=6, so 
the name in the previous example is thought to be "+04>-4" as the whole loop 
evaluates against the first char "+" and does not notice the name end marker ">".

http://git.musl-libc.org/cgit/musl/tree/src/time/__tz.c#n87

```
     if (**p == '<') {
         ++*p;
         for (i=0; **p!='>' && i<TZNAME_MAX; i++) <---- culprit: **p remains 
constant
             d[i] = (*p)[i];
         ++*p;
     } else {
         for (i=0; ((*p)[i]|32)-'a'<26U && i<TZNAME_MAX; i++)
             d[i] = (*p)[i];
     }
     *p += i;
     d[i] = 0;
```

Function "do_tzset" uses "getname" to both find the string and to move the 
pointer "s" forward. As the end of the timezone name is evaluated wrongly, 
the offset calculation & DST detection will also fail, as they start from the 
wrong place.

http://git.musl-libc.org/cgit/musl/tree/src/time/__tz.c#n219

```
     getname(std_name, &s);
     __tzname[0] = std_name;
     __timezone = getoff(&s);
     getname(dst_name, &s);
     __tzname[1] = dst_name;
```

I patched "getname" by replacing **p with (*p)[i] to make it to evaluate the 
correct character:

```
--- a/src/time/__tz.c
+++ b/src/time/__tz.c
@@ -87,7 +87,7 @@
      int i;
      if (**p == '<') {
          ++*p;
-        for (i=0; **p!='>' && i<TZNAME_MAX; i++)
+        for (i=0; (*p)[i]!='>' && i<TZNAME_MAX; i++)
              d[i] = (*p)[i];
          ++*p;
      } else {

```

I am not sure if the fix is optimal, but it seems to work.

After that change I am finally able to select timezones with quoted names and 
see correct times:

```
root@lede:~# cat /etc/TZ ; date
EET-2EEST,M3.5.0/3,M10.5.0/4
Tue Oct 18 21:46:41 EEST 2016

root@lede:~# echo "UTC" > /etc/TZ
root@lede:~# cat /etc/TZ ; date
UTC
Tue Oct 18 18:46:53 UTC 2016

root@lede:~# echo "<+04>-4" > /etc/TZ
root@lede:~# cat /etc/TZ ; date
<+04>-4
Tue Oct 18 22:47:17 +04 2016

root@lede:~# echo "<+00>0<+02>-2,M3.5.0/1,M10.5.0/3" > /etc/TZ
root@lede:~# cat /etc/TZ ; date
<+00>0<+02>-2,M3.5.0/1,M10.5.0/3
Tue Oct 18 20:48:10 +02 2016

root@lede:~# echo "<-03>3" > /etc/TZ
root@lede:~# cat /etc/TZ ; date
<-03>3
Tue Oct 18 15:48:41 -03 2016
```



      reply	other threads:[~2016-10-19  6:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-31 15:50 Hannu Nyman
2016-03-31 16:06 ` Rich Felker
2016-03-31 16:47   ` Hannu Nyman
2016-10-19  6:40     ` Hannu Nyman [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f6468f7c-f322-ed8d-ab27-7afbd48138ea@iki.fi \
    --to=hannu.nyman@iki.fi \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).