[PATCH] strftime: use tzname if TM_ZONE is NULL

Craig Howland howland@LGSInnovations.com
Wed Mar 25 23:25:00 GMT 2015


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



More information about the Newlib mailing list