Subject: Re: Invalid timezone (tzalloc failure) treated as out-of-memory

From: Paul Eggert <[email-masked]>
Date: Thu, 15 Mar 2018 09:43:20 -0700

On 03/12/2018 12:10 PM, Valery Ushakov wrote:
> -  else if (EQ (zone, Qt))
> +  else if (EQ (zone, Qt)
> +	   || (INTEGERP (zone) && XINT (zone) == 0))

Thanks for diagnosing the problem. If I understand things correctly, we 
can do a more-general fix, which should work for any used-in-practice 
time zone that is an integer hour offset from UTC. I installed the 
attached patch into master; please give it a try. I don't have easy 
access to NetBSD and would appreciate your testing it on NetBSD 6 and 7. 
I think this problem is limited to older NetBSD and so is not worth 
testing for in configure.ac (as 'configure' is pretty slow already).

From 64a1da4989b0551481600facb1781ac92089d182 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Thu, 15 Mar 2018 09:35:33 -0700
Subject: [PATCH] Improve port to NetBSD tzalloc
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported by Valery Ushakov (Bug#30738#13).
* src/editfns.c (tzlookup) [__NetBSD_Version__ < 700000000]:
If tzalloc fails for any reason other than memory exhaustion,
assume it’s because NetBSD 6 does not support tzalloc on
POSIX-format TZ strings, and fall back on tzdb if possible.
---
 src/editfns.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/editfns.c b/src/editfns.c
index 6ecc83fc30..d26319441b 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -204,6 +204,18 @@ tzlookup (Lisp_Object zone, bool settz)
 	invalid_time_zone_specification (zone);
 
       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
+	  && XINT (zone) % (60 * 60) == 0)
+	{
+	  sprintf (tzbuf, "Etc/GMT%+"pI"d", - (XINT (zone) / (60 * 60)));
+	  new_tz = tzalloc (zone_string);
+	}
+#endif
+
       if (!new_tz)
 	{
 	  if (errno == ENOMEM)
-- 
2.14.3