Seg Fault in strftime

Michael Enright
Fri Jul 31 00:16:00 GMT 2015

In a thread about navigating a stackdump to find out what's going
wrong, I posted the output of a GDB session as follows.

On Thu, Jul 30, 2015 at 11:48 AM, Michael Enright  wrote:
> (gdb) print tznam
> $3 = 0xc07a4000 <error: Cannot access memory at address 0xc07a4000>
> (gdb) list
> 1339                    tznam = _tzname[tim_p->tm_isdst > 0];
> 1340                  /* Note that in case of wcsftime this loop only works for
> 1341                     timezone abbreviations using the portable
> codeset (aka ASCII).
> 1342                     This seems to be the case, but if that ever
> changes, this
> 1343                     loop needs revisiting. */
> 1344                  size = strlen (tznam);
> 1345                  for (i = 0; i < size; i++)
> 1346                    {
> 1347                      if (count < maxsize - 1)
> 1348                        s[count++] = tznam[i];
> (gdb) print _tzname
> $4 = {0x800cfc48 "\200", <incomplete sequence \356\066>, 0x800cfc44 "PDT"}
> (gdb) print _tzname[0]
> $5 = 0x800cfc48 "\200", <incomplete sequence \356\066>
> (gdb) print _tzname[1]
> $6 = 0x800cfc44 "PDT"

This is a little misleading. The code at or near line 1339 looks like this:
1331 #if defined (__CYGWIN__)
1332     /* See above. */
1333      extern const char *__cygwin_gettzname (const struct tm *tmp);
1334      tznam = __cygwin_gettzname (tim_p);
1335 #elif defined (__TM_ZONE)
1336      tznam = tim_p->__TM_ZONE;
1337 #endif
1338      if (!tznam)
1339        tznam = _tzname[tim_p->tm_isdst > 0];

The tznam is set from the tmzone member and when this happens that
member is garbage. This member is garbage POSSIBLY because of a
configuration option in libmozjs. The calling code is in prmjtime.cpp
fills in a struct tm from Spidermonkey's own broken-down time
structure, 'a', and then if the configuration enables, it makes
*another* struct tm with more fields filled in in order to get
a.tm_zone's proper value. My guess is that the path is not enabled but
the bits delivered to me do not disclose whether this righteous code
path is enabled. __cygwin_gettzname is evidently compiled to expect
the tm_zone member to exist because GDB shows it does exist.

So did any aspect of this change recently? The application and library
were getting along okay before I did cygwin updates. The last time I
had tried to run this code was early June, at which time I was running
it dozens of times a day.

Also it appears that the tm_zone member is an extension. I haven't
been able to find POSIX guidance about how applications are supposed
use struct tm in compliance in the presence of implementation-defined
fields. POSIX example code shows a usage that does access the 'at
least' fields. The language allows for implementation-defined fields.
No mechanism is provided within POSIX to allow an application to
discover additional fields and take care of them. It seems to me that
an application can then assume that when it provides a struct tm as
input, filling in the time and date reasonably, it is always
sufficient to fill in the 'at least' fields and the implementation is
the one who has to assume that the rest of the fields might not be
filled in.

Problem reports:
Unsubscribe info:

More information about the Cygwin mailing list