commit b7c6b54bffba40a06b9337d56c63ed34e97c3de5
Author: Dmitry Goncharov <dgoncharov@users.sf.net>
Date:   Mon Oct 24 18:36:19 2022 -0400

    [SV 63333] Handle temporary file failures.
    
    Keep running without output sync, if cannot create an output sync temporary
    lock file.
    Die, if cannot store make code from stdin to a temporary file.
    
    * misc.c (get_tmppath): Keep running on failure to generate a temporary file
    name.
    (get_tmpfd): Keep running on failure to open or unlink a temporary file.
    (get_tmpfile): Keep running on failure to open a temporary file.
    * posixos.c (os_anontmp): Keep running on failure to open an anonymous
    temporary file.
    * output.c (setup_tmpfile): Print an error on failure to create an output sync
    lock file.
    * main.c (main): Die on failure to store makefile from stdin to a temporary
    file.
    (main): Fix a memory leak.
    * tests/scripts/features/output-sync: Add tests.
    * tests/scripts/features/temp_stdin: Ditto.

diff --git a/src/main.c b/src/main.c
index eec93656..b046e3d9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1923,13 +1923,19 @@ main (int argc, char **argv, char **envp)
                and thus re-read the makefiles, we read standard input
                into a temporary file and read from that.  */
             FILE *outfile;
-            char *newnm;
+            char *newnm = NULL;
 
             if (stdin_offset >= 0)
               O (fatal, NILF,
                  _("Makefile from standard input specified twice"));
 
             outfile = get_tmpfile (&newnm);
+            if (!outfile)
+              {
+                free (newnm);
+                O (fatal, NILF,
+                    _("Cannot store makefile from stdin to a temporary file"));
+              }
 
             while (!feof (stdin) && ! ferror (stdin))
               {
diff --git a/src/misc.c b/src/misc.c
index bf6fe7ca..c559ba79 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -20,6 +20,7 @@ this program.  If not, see <https://www.gnu.org/licenses/>.  */
 #include "os.h"
 #include "debug.h"
 
+#include <assert.h>
 /* GNU make no longer supports pre-ANSI89 environments.  */
 
 #include <stdarg.h>
@@ -650,11 +651,19 @@ get_tmppath ()
 # ifdef HAVE_MKTEMP
   path = get_tmptemplate ();
   if (*mktemp (path) == '\0')
-    pfatal_with_name ("mktemp");
+    {
+      OSS (error, NILF,
+           _("Cannot generate temp path from %s: %s"), path, strerror (errno));
+      return NULL;
+    }
 # else
   path = xmalloc (L_tmpnam + 1);
   if (tmpnam (path) == NULL)
-    pfatal_with_name ("tmpnam");
+    {
+      OS (error, NILF,
+        _("Cannot generate temp name: %s"), strerror (errno));
+      return NULL;
+    }
 # endif
 
   return path;
@@ -684,13 +693,19 @@ get_tmpfd (char **name)
   EINTRLOOP (fd, mkstemp (tmpnm));
 #else
   tmpnm = get_tmppath ();
+  if (!tmpnm)
+    return -1;
 
   /* Can't use mkstemp(), but try to guard against a race condition.  */
   EINTRLOOP (fd, open (tmpnm, O_CREAT|O_EXCL|O_RDWR, 0600));
 #endif
   if (fd < 0)
-    OSS (fatal, NILF,
-         _("create temporary file %s: %s"), tmpnm, strerror (errno));
+    {
+      OSS (error, NILF,
+           _("Cannot create temporary file %s: %s"), tmpnm, strerror (errno));
+      free (tmpnm);
+      return -1;
+    }
 
   if (name)
     *name = tmpnm;
@@ -699,8 +714,8 @@ get_tmpfd (char **name)
       int r;
       EINTRLOOP (r, unlink (tmpnm));
       if (r < 0)
-        OSS (fatal, NILF,
-             _("unlink temporary file %s: %s"), tmpnm, strerror (errno));
+        OSS (error, NILF,
+             _("Cannot unlink temporary file %s: %s"), tmpnm, strerror (errno));
       free (tmpnm);
     }
 
@@ -709,7 +724,9 @@ get_tmpfd (char **name)
 
 /* Return a FILE* for a temporary file, opened in the safest way possible.
    Set name to point to an allocated buffer containing the name of the file.
-   Note, this cannot be NULL!  */
+   Note, name cannot be NULL!
+   The caller has to free the allocated name, whether get_tmpfile succeeded or
+   not.  */
 FILE *
 get_tmpfile (char **name)
 {
@@ -718,30 +735,38 @@ get_tmpfile (char **name)
   FILE *file;
 
 #if defined(HAVE_FDOPEN)
-  int fd = get_tmpfd (name);
+  int fd;
+  assert (name);
+  fd = get_tmpfd (name);
+  if (fd < 0)
+    return NULL;
+  assert (*name);
 
   ENULLLOOP (file, fdopen (fd, tmpfile_mode));
   if (file == NULL)
-    OSS (fatal, NILF,
+    OSS (error, NILF,
          _("fdopen: temporary file %s: %s"), *name, strerror (errno));
 #else
   /* Preserve the current umask, and set a restrictive one for temp files.  */
   mode_t mask = umask (0077);
-  int err;
 
+  assert (name);
   *name = get_tmppath ();
+  if (!*name)
+    return NULL;
 
   /* Although this fopen is insecure, it is executed only on non-fdopen
      platforms, which should be a rarity nowadays.  */
 
   ENULLLOOP (file, fopen (*name, tmpfile_mode));
   if (file == NULL)
-    OSS (fatal, NILF,
+    OSS (error, NILF,
          _("fopen: temporary file %s: %s"), *name, strerror (errno));
 
   umask (mask);
 #endif
 
+  assert (*name);
   return file;
 }
 
diff --git a/src/output.c b/src/output.c
index 43eb2f06..9808b515 100644
--- a/src/output.c
+++ b/src/output.c
@@ -248,6 +248,9 @@ setup_tmpfile (struct output *out)
 
   /* If we failed to create a temp file, disable output sync going forward.  */
  error:
+  O (error, NILF,
+     _("Cannot open output-sync lock file, suppressing output-sync."));
+
   output_close (out);
   output_sync = OUTPUT_SYNC_NONE;
   osync_clear ();
diff --git a/src/posixos.c b/src/posixos.c
index 48e8cf5c..f586b520 100644
--- a/src/posixos.c
+++ b/src/posixos.c
@@ -860,12 +860,15 @@ os_anontmp ()
       FILE *tfile;
       ENULLLOOP (tfile, tmpfile ());
       if (!tfile)
-        pfatal_with_name ("tmpfile");
+        {
+          OS (error, NILF, _("tmpfile: %s"), strerror (errno));
+          return -1;
+        }
       umask (mask);
 
       EINTRLOOP (fd, dup (fileno (tfile)));
       if (fd < 0)
-        pfatal_with_name ("dup");
+        OS (error, NILF, _("dup: %s"), strerror (errno));
       fclose (tfile);
     }
 #endif 