[PATCH] strftime: use tzname if TM_ZONE is NULL

Corinna Vinschen vinschen@redhat.com
Mon Mar 30 10:41:00 GMT 2015


On Mar 25 18:09, Craig Howland wrote:
> On 03/25/2015 05:46 PM, Yaakov Selkowitz wrote:
> >* libc/time/strftime.c (strftime) <%Z>: Initialize tznam to NULL.
> >Use _tzname as fallback if TM_ZONE is NULL.
> >---
> >The following testcase (based on a real-world crash of WebKitGTK+ on
> >my system when attempting to authorize a Google account) crashes on
> >Cygwin:
> >
> >#include <time.h>
> >#include <stdio.h>
> >#include <string.h>
> >
> >int main (void) {
> >	struct tm tm = { 53, 54, 18, 23, 2, 115, 1, 81, 1, -18000, NULL };
> >	char s[32];
> >	/* tzset(); */
> >	strftime (s, 32, "%Z", &tm);
> >	printf("%d: %s\n", strlen(s), s);
> >	return 0;
> >}
> >
> >The crash was due to a strlen(NULL) a few lines later, which should NOT
> >happen.  glibc takes this a step further and calls tzset() if not yet
> >called so that the returned string matches the local timezone (instead
> >of "GMT", or on Cygwin, " ").  The question is how to (portably)
> >determine if tzset() has been called already or not (e.g. a global
> >variable?).
> >
> >  newlib/libc/time/strftime.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> >
> >diff --git a/newlib/libc/time/strftime.c b/newlib/libc/time/strftime.c
> >index 7db3383..ee604c2 100644
> >--- a/newlib/libc/time/strftime.c
> >+++ b/newlib/libc/time/strftime.c
> >@@ -1311,7 +1311,7 @@ recurse:
> >  	  if (tim_p->tm_isdst >= 0)
> >  	    {
> >  	      size_t size;
> >-	      const char *tznam;
> >+	      const char *tznam = NULL;
> >  	      TZ_LOCK;
> >  #if defined (__CYGWIN__)
> >@@ -1320,9 +1320,9 @@ recurse:
> >  	      tznam = __cygwin_gettzname (tim_p);
> >  #elif defined (__TM_ZONE)
> >  	      tznam = tim_p->__TM_ZONE;
> >-#else
> >-	      tznam = _tzname[tim_p->tm_isdst > 0];
> >  #endif
> >+	      if (!tznam)
> >+		tznam = _tzname[tim_p->tm_isdst > 0];
> >  	      /* Note that in case of wcsftime this loop only works for
> >  	         timezone abbreviations using the portable codeset (aka ASCII).
> >  		 This seems to be the case, but if that ever changes, this
> There was a discussion under way a while ago related to tzset(), the results
> of which never were implemented (mainly due to it slipping off my horizon).
> See https://sourceware.org/ml/newlib/2013/msg00443.html for the final word.
> In short, ctime(), localtime(), mktime(), and strftime() all should call
> tzset(), while it should be removed from setenv(). Checking for having been
> called already is really not needed, since the user can change the
> environment at any time, so that tzset() really needs to be called every
> time.
> Craig

I agree.  I took another look into glibc's implementation of strftime
and it's calling tzset whenever the 'z' or 'Z' format is used.  It just
keeps a marker around as an extra parameter so it never calls tzset more
than once, even if the function recurses.


Corinna

-- 
Corinna Vinschen
Cygwin Maintainer
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20150330/729c3d87/attachment.sig>


More information about the Newlib mailing list