Package: zsh
Version: 4.3.12-1
Severity: normal
Tags: patch

Dear Maintainer,

  after upgrading to zsh 4.3.12 (in debian), I am having problems running
midnight commander in zsh (going back to zsh version 4.3.10 it works fine).
The symptom is that when trying to use the subshell in mc, it complains about:

precmd: 15: bad file descriptor

and the mc session get hanged. It turned out to be a bug in zsh and the upstream
authors found a solution described here:

http://www.zsh.org/mla/workers/2011/msg00988.html
http://www.zsh.org/mla/workers/2011/msg00994.html

Would it be possible to include the two patches mentioned at that thread into
currect debian zsh 4.3.12 until new upstream zsh release gets out ?

Thanks,
Pavel


-- System Information:
Debian Release: wheezy/sid
  APT prefers squeeze
  APT policy: (950, 'squeeze'), (950, 'sid'), (840, 
'testing-proposed-updates'), (840, 'testing'), (740, 'unstable'), (738, 
'experimental'), (540, 'proposed-updates'), (540, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.0.0-1-amd64-ipnp-n22a-5 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=cs_CZ.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages zsh depends on:
ii  libc6         2.13-21 
ii  libcap2       1:2.22-1
ii  libncursesw5  5.9-1   

Versions of packages zsh recommends:
ii  libc6     2.13-21
ii  libpcre3  8.12-4 

Versions of packages zsh suggests:
ii  zsh-doc  4.3.12-1

-- no debconf information
--- old/Src/exec.c	19 Jul 2011 09:26:57 -0000	1.199
+++ new/Src/exec.c	19 Jul 2011 09:45:19 -0000
@@ -2975,17 +2975,16 @@
 			fn->fd1 = (int)getintvalue(v);
 			if (errflag)
 			    bad = 1;
-			else if (fn->fd1 > max_zsh_fd)
-			    bad = 3;
-			else if (fn->fd1 >= 10 &&
+			else if (fn->fd1 <= max_zsh_fd) {
+			    if (fn->fd1 >= 10 &&
 				 fdtable[fn->fd1] == FDT_INTERNAL)
-			    bad = 4;
+				bad = 3;
+			}
 		    }
 		    if (bad) {
 			const char *bad_msg[] = {
 			    "parameter %s does not contain a file descriptor",
 			    "can't close file descriptor from readonly parameter %s",
-			    "file descriptor %d out of range, not closed",
 			    "file descriptor %d used by shell, not closed"
 			};
 			if (bad > 2)
@@ -2995,11 +2994,18 @@
 			execerr();
 		    }
 		}
+		/*
+		 * Note we may attempt to close an fd beyond max_zsh_fd:
+		 * OK as long as we never look in fdtable for it.
+ 		 */
 		if (!forked && fn->fd1 < 10 && save[fn->fd1] == -2)
 		    save[fn->fd1] = movefd(fn->fd1);
 		if (fn->fd1 < 10)
 		    closemn(mfds, fn->fd1);
-		zclose(fn->fd1);
+		if (zclose(fn->fd1) < 0) {
+		    zwarn("failed to close file descriptor %d: %e",
+			  fn->fd1, errno);
+		}
 		break;
 	    case REDIR_MERGEIN:
 	    case REDIR_MERGEOUT:
--- old/Src/utils.c	19 Jun 2011 16:26:11 -0000	1.259
+++ new/Src/utils.c	19 Jul 2011 09:45:19 -0000
@@ -1802,22 +1802,20 @@
 {
     if (fd >= 0) {
 	/*
-	 * We sometimes zclose() an fd twice where the second
-	 * time is a catch-all in case there was a failure using
-	 * the fd.  This is harmless but we need to trap it
-	 * for the error check here.
+	 * Careful: we allow closing of arbitrary fd's, beyond
+	 * max_zsh_fd.  In that case we don't try anything clever.
 	 */
-	DPUTS2(fd > max_zsh_fd && fdtable[fd] != FDT_UNUSED,
-	       "BUG: fd is %d, max_zsh_fd is %d", fd, max_zsh_fd);
-	if (fdtable[fd] == FDT_FLOCK)
-	    fdtable_flocks--;
-	fdtable[fd] = FDT_UNUSED;
-	while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED)
-	    max_zsh_fd--;
-	if (fd == coprocin)
-	    coprocin = -1;
-	if (fd == coprocout)
-	    coprocout = -1;
+	if (fd <= max_zsh_fd) {
+	    if (fdtable[fd] == FDT_FLOCK)
+		fdtable_flocks--;
+	    fdtable[fd] = FDT_UNUSED;
+	    while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED)
+		max_zsh_fd--;
+	    if (fd == coprocin)
+		coprocin = -1;
+	    if (fd == coprocout)
+		coprocout = -1;
+	}
 	return close(fd);
     }
     return -1;
--- old/Test/A04redirect.ztst	6 Mar 2011 21:37:38 -0000	1.18
+++ new/Test/A04redirect.ztst	19 Jul 2011 09:45:19 -0000
@@ -155,9 +155,12 @@
   (exec 3<&-
   read foo <&-)
 1:'<&-' redirection
+?(eval):1: failed to close file descriptor 3: bad file descriptor
+?(eval):2: failed to close file descriptor 0: bad file descriptor
 
   print foo >&-
 0:'>&-' redirection
+?(eval):1: failed to close file descriptor 1: bad file descriptor
 
   fn() { local foo; read foo; print $foo; }
   coproc fn
--- old/Src/exec.c	23 Jun 2011 19:29:24 -0000	1.198
+++ new/Src/exec.c	18 Jul 2011 15:20:29 -0000
@@ -3008,11 +3008,17 @@
 		if (!checkclobberparam(fn))
 		    fil = -1;
 		else if (fn->fd2 > 9 &&
-			 (fn->fd2 > max_zsh_fd ||
-			  (fdtable[fn->fd2] != FDT_UNUSED &&
-			   fdtable[fn->fd2] != FDT_EXTERNAL) ||
-			  fn->fd2 == coprocin ||
-			  fn->fd2 == coprocout)) {
+			 /*
+			  * If the requested fd is > max_zsh_fd,
+			  * the shell doesn't know about it.
+			  * Just assume the user knows what they're
+			  * doing.
+			  */
+			 (fn->fd2 <= max_zsh_fd &&
+			  ((fdtable[fn->fd2] != FDT_UNUSED &&
+			    fdtable[fn->fd2] != FDT_EXTERNAL) ||
+			   fn->fd2 == coprocin ||
+			   fn->fd2 == coprocout))) {
 		    fil = -1;
 		    errno = EBADF;
 		} else {

Reply via email to