about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2016-09-29 11:16:24 -0700
committerBarton E. Schaefer <schaefer@zsh.org>2016-09-29 11:16:24 -0700
commite61ed2b80d60ca095006d7512f90c07e6c572ee0 (patch)
treef0a8e9d6b22efd84057d7ba9646b1173d9df366d
parent6ce696f35236dc4c1b6249c6f1e7f64cc95a6046 (diff)
downloadzsh-e61ed2b80d60ca095006d7512f90c07e6c572ee0.tar.gz
zsh-e61ed2b80d60ca095006d7512f90c07e6c572ee0.tar.xz
zsh-e61ed2b80d60ca095006d7512f90c07e6c572ee0.zip
39470: failure to open a supposedly unique temp file name should result in an error
Also band-aid for signal-related race conditions in temp file name generation
-rw-r--r--ChangeLog6
-rw-r--r--Src/exec.c16
-rw-r--r--Src/utils.c4
3 files changed, 21 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index ca9d23b57..f93bdb10a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-29  Barton E. Schaefer  <schaefer@zsh.org>
+
+	* 39470: Src/exec.c, Src/utils.c: failure to open a supposedly
+	unique temp file name should result in an error; band-aid for
+	signal-related race conditions in temp file name generation
+
 2016-09-29  Peter Stephenson  <p.stephenson@samsung.com>
 
 	* 39502: Src/exec.c, Test/A01grammar.ztst: need to fork for
diff --git a/Src/exec.c b/Src/exec.c
index e3915ddfe..04868bd37 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -4412,11 +4412,17 @@ getoutputfile(char *cmd, char **eptr)
 	    untokenize(s);
     }
 
-    addfilelist(nam, 0);
+    if (!s)             /* Unclear why we need to do this before open() */
+	child_block();  /* but it has been so for a long time: leave it */
 
-    if (!s)
-	child_block();
-    fd = open(nam, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0600);
+    if ((fd = open(nam, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0600)) < 0) {
+	zerr("process substitution failed: %e", errno);
+	free(nam);
+	if (!s)
+	    child_unblock();
+	return NULL;
+    }
+    addfilelist(nam, 0);
 
     if (s) {
 	/* optimised here-string */
@@ -4427,7 +4433,7 @@ getoutputfile(char *cmd, char **eptr)
 	return nam;
     }
 
-    if (fd < 0 || (cmdoutpid = pid = zfork(NULL)) == -1) {
+    if ((cmdoutpid = pid = zfork(NULL)) == -1) {
 	/* fork or open error */
 	child_unblock();
 	return nam;
diff --git a/Src/utils.c b/Src/utils.c
index b434821e5..db4352908 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -2164,6 +2164,7 @@ gettempfile(const char *prefix, int use_heap, char **tempname)
 #if HAVE_MKSTEMP
     char *suffix = prefix ? ".XXXXXX" : "XXXXXX";
 
+    queue_signals();
     if (!prefix && !(prefix = getsparam("TMPPREFIX")))
 	prefix = DEFAULT_TMPPREFIX;
     if (use_heap)
@@ -2180,6 +2181,7 @@ gettempfile(const char *prefix, int use_heap, char **tempname)
 #else
     int failures = 0;
 
+    queue_signals();
     do {
 	if (!(fn = gettempname(prefix, use_heap))) {
 	    fd = -1;
@@ -2193,6 +2195,8 @@ gettempfile(const char *prefix, int use_heap, char **tempname)
     } while (errno == EEXIST && ++failures < 16);
 #endif
     *tempname = fn;
+
+    unqueue_signals();
     return fd;
 }