Subject: bug#30738: Invalid timezone (tzalloc failure) treated as out-of-memory

From: Paul Eggert <[email-masked]>
Date: Mon, 19 Mar 2018 16:55:25 -0700

On 03/19/2018 09:29 AM, Valery Ushakov wrote:
> special casing 0 is still a good idea as it saves a call to
> tzalloc().

Fair enough; I installed the first attached patch.

> this patch also needs to #include <sys/param.h>
> where __NetBSD_Version__ is defined.

Thanks, I installed the second attached patch to do that.

> tzbuf_format can
> probably drop that artisanal &"-"[...] and its corresponding %s, and
> just pass -hour instead.

That would mishandle time zones like -00:30:00 (i.e., 30 minutes behind 
UTC). That is, the sign is a property of the minutes and the seconds 
too, not just the hours.

>From 7a7ee53dbdcf489050653f04ba3d0c491245c5fa Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Mon, 19 Mar 2018 13:29:22 -0700
Subject: [PATCH] Tune time zone 0

* src/editfns.c (tzlookup): Treat time zone 0 like t, for speed.
Suggested by Valery Ushakov (Bug#30738#19).
---
 src/editfns.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/editfns.c b/src/editfns.c
index d26319441b..cb7353a48c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -147,7 +147,7 @@ tzlookup (Lisp_Object zone, bool settz)
 
   if (NILP (zone))
     return local_tz;
-  else if (EQ (zone, Qt))
+  else if (EQ (zone, Qt) || EQ (zone, make_number (0)))
     {
       zone_string = "UTC0";
       new_tz = utc_tz;
-- 
2.14.3

>From 6d12e7af88b8287b8dd520aa3a3470f7f112cfe0 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Mon, 19 Mar 2018 16:49:09 -0700
Subject: [PATCH] Improve port to NetBSD tzalloc

Problem reported by Valery Ushakov (Bug#30738#22).
* src/editfns.c (HAVE_TZALLOC_BUG): New macro.
(tzlookup): Use it.  Compile on all platforms, not just on NetBSD.
---
 src/editfns.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/editfns.c b/src/editfns.c
index cb7353a48c..7e35fe8797 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -48,6 +48,16 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <float.h>
 #include <limits.h>
 
+#ifdef HAVE_TIMEZONE_T
+# include <sys/param.h>
+# if defined __NetBSD_Version__ && __NetBSD_Version__ < 700000000
+#  define HAVE_TZALLOC_BUG true
+# endif
+#endif
+#ifndef HAVE_TZALLOC_BUG
+# define HAVE_TZALLOC_BUG false
+#endif
+
 #include <c-ctype.h>
 #include <intprops.h>
 #include <stdlib.h>
@@ -205,16 +215,14 @@ tzlookup (Lisp_Object zone, bool settz)
 
       new_tz = tzalloc (zone_string);
 
-#if defined __NetBSD_Version__ && __NetBSD_Version__ < 700000000
-      /* NetBSD 6 tzalloc mishandles POSIX TZ strings (Bug#30738).
-	 If possible, fall back on tzdb.  */
-      if (!new_tz && errno != ENOMEM && plain_integer
+      if (HAVE_TZALLOC_BUG && !new_tz && errno != ENOMEM && plain_integer
 	  && XINT (zone) % (60 * 60) == 0)
 	{
+	  /* tzalloc mishandles POSIX strings; fall back on tzdb if
+	     possible (Bug#30738).  */
 	  sprintf (tzbuf, "Etc/GMT%+"pI"d", - (XINT (zone) / (60 * 60)));
 	  new_tz = tzalloc (zone_string);
 	}
-#endif
 
       if (!new_tz)
 	{
-- 
2.14.3