Subject: bug#21020: 24.4; `display-time-world' tampers with TZ

From: Eli Zaretskii <[email-masked]>
Date: Mon, 27 Jul 2015 20:29:43 +0300

> Date: Mon, 27 Jul 2015 15:29:33 +0300
> From: Eli Zaretskii <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
> After the above commit, Emacs builds and generally seems to work, but
> crashes inside icalendar tests.  Seems like something with heap
> corruption.  I'm looking into that now.

The reason seems to be these assignments in time_rz.c:

  static bool
  revert_tz (timezone_t tz)
  {
    if (tz == local_tz)
      return true;
    else
      {
	int saved_errno = errno;
	bool ok = change_env (tz);
	if (!ok)
	  saved_errno = errno;
  #if HAVE_TZNAME
	if (!ok)
	  tzname_address = NULL;
	if (tzname_address)
	  {
	    char *old_value = *tzname_address;
	    *tzname_address = tzname_value;  <<<<<<<<<<<<<<<<<<<<<<<
	    tzname_value = old_value;
	  }
  #endif
	tzfree (tz);
	errno = saved_errno;
	return ok;
      }
  }

  static void
  restore_tzname (void)
  {
  #if HAVE_TZNAME
    if (tzname_address)
      {
	*tzname_address = tzname_value;    <<<<<<<<<<<<<<<<<<<<<<
	tzname_address = NULL;
      }
  #endif
  }

If I ifdef away the 2 marked lines, the test suite runs flawlessly to
completion.

tzname_address is the address of one of the members of the tzname[]
array, which holds pointers into the bowels of libc.  I don't know why
overwriting them with our values causes such trouble, but even if this
is supposed to work, it makes me nervous.  I'm not even sure I
understand completely why this trick is needed (can you explain?).  In
any case, can we please do this in some less intrusive way, e.g., by
copying the TZ names to our private storage?

Thanks.