From d9b364304b9f56e7c94252e84829efba3804417b Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 9 Aug 2021 19:35:09 -0700
Subject: [PATCH 1/2] Port to platforms where malloc does not set errno
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Problem reported via clang by Jan Engelhardt in:
https://mm.icann.org/pipermail/tz/2021-August/030319.html
* date.c (dogmt):
* localtime.c (tzload, tzalloc) [!HAVE_MALLOC_ERRNO]:
* zdump.c (xmalloc):
* zic.c (memcheck):
Don’t assume failing malloc sets errno.
* private.h (HAVE_MALLOC_ERRNO): Default to 1.
(EINVAL): Default to ERANGE since even C89 requires ERANGE.
This is probably just theoretical.
(ENOMEM): Default to EINVAL.
---
 NEWS        |  6 ++++++
 date.c      |  2 +-
 localtime.c |  9 +++++----
 private.h   | 11 +++++++++++
 zdump.c     |  2 +-
 zic.c       |  2 +-
 6 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index f53e431..1bf9cf3 100644
--- a/NEWS
+++ b/NEWS
@@ -141,6 +141,12 @@ Unreleased, experimental changes
     lower time bound and exclusive for the upper.  Formerly they were
     inconsistent.  (Confusion noted by Martin Burnicki.)
 
+  Changes to build procedure
+
+    You can now compile with -DHAVE_MALLOC_ERRNO=0 to port to
+    non-POSIX hosts where malloc doesn't set errno.
+    (Problem reported by Jan Engelhardt.)
+
 
 Release 2021a - 2021-01-24 10:54:57 -0800
 
diff --git a/date.c b/date.c
index 8173b77..b04d3f2 100644
--- a/date.c
+++ b/date.c
@@ -138,7 +138,7 @@ dogmt(void)
 			continue;
 		fakeenv = malloc((n + 2) * sizeof *fakeenv);
 		if (fakeenv == NULL) {
-			perror(_("Memory exhausted"));
+			fprintf(stderr, _("date: Memory exhausted\n"));
 			errensure();
 			exit(retval);
 		}
diff --git a/localtime.c b/localtime.c
index c986be5..a70b67a 100644
--- a/localtime.c
+++ b/localtime.c
@@ -736,9 +736,9 @@ tzload(char const *name, struct state *sp, bool doextend)
 {
 #ifdef ALL_STATE
   union local_storage *lsp = malloc(sizeof *lsp);
-  if (!lsp)
-    return errno;
-  else {
+  if (!lsp) {
+    return HAVE_MALLOC_ERRNO ? errno : ENOMEM;
+  } else {
     int err = tzloadbody(name, sp, doextend, lsp);
     free(lsp);
     return err;
@@ -1438,7 +1438,8 @@ tzalloc(char const *name)
       errno = err;
       return NULL;
     }
-  }
+  } else if (!HAVE_MALLOC_ERRNO)
+    errno = ENOMEM;
   return sp;
 }
 
diff --git a/private.h b/private.h
index 9dbb071..98ead55 100644
--- a/private.h
+++ b/private.h
@@ -66,6 +66,10 @@
 #define HAVE_LINK		1
 #endif /* !defined HAVE_LINK */
 
+#ifndef HAVE_MALLOC_ERRNO
+#define HAVE_MALLOC_ERRNO 1
+#endif
+
 #ifndef HAVE_POSIX_DECLS
 #define HAVE_POSIX_DECLS 1
 #endif
@@ -160,9 +164,16 @@
 
 #include <errno.h>
 
+#ifndef EINVAL
+# define EINVAL ERANGE
+#endif
+
 #ifndef ENAMETOOLONG
 # define ENAMETOOLONG EINVAL
 #endif
+#ifndef ENOMEM
+# define ENOMEM EINVAL
+#endif
 #ifndef ENOTSUP
 # define ENOTSUP EINVAL
 #endif
diff --git a/zdump.c b/zdump.c
index b3f3448..f2ff442 100644
--- a/zdump.c
+++ b/zdump.c
@@ -140,7 +140,7 @@ xmalloc(size_t size)
 {
   void *p = malloc(size);
   if (!p) {
-    perror(progname);
+    fprintf(stderr, _("%s: Memory exhausted\n"), progname);
     exit(EXIT_FAILURE);
   }
   return p;
diff --git a/zic.c b/zic.c
index ddcb1e5..4c55f1c 100644
--- a/zic.c
+++ b/zic.c
@@ -450,7 +450,7 @@ static void *
 memcheck(void *ptr)
 {
 	if (ptr == NULL)
-		memory_exhausted(strerror(errno));
+	  memory_exhausted(strerror(HAVE_MALLOC_ERRNO ? errno : ENOMEM));
 	return ptr;
 }
 
-- 
2.30.2

