[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

ksh bug fixes



The following ksh diff needs wide testing.  It does the following:

 1) proper error message for bad substitution.
    Before:
	$ echo ${a[_(_at_)_]:foo}
	ksh: : bad substitution
    After:
	$ echo ${a[_(_at_)_]:foo}
	ksh: ${a[_(_at_)_]:foo}: bad substitution

 2) fix a core dump for "echo ${a[_(_at_)_]:foo}".

 3) fix a use-after-free bug (from otto@)

Index: bin/ksh/c_sh.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/c_sh.c,v
retrieving revision 1.17
diff -u -r1.17 c_sh.c
--- bin/ksh/c_sh.c	13 Mar 2003 09:03:07 -0000	1.17
+++ bin/ksh/c_sh.c	10 Dec 2004 19:26:07 -0000
@@ -558,7 +558,7 @@
 		how = LSHELL;
 	}
 
-	quitenv();	/* get rid of any i/o redirections */
+	quitenv(NULL);	/* get rid of any i/o redirections */
 	unwind(how);
 	/*NOTREACHED*/
 	return 0;
Index: bin/ksh/eval.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/eval.c,v
retrieving revision 1.17
diff -u -r1.17 eval.c
--- bin/ksh/eval.c	9 Dec 2004 11:32:07 -0000	1.17
+++ bin/ksh/eval.c	10 Dec 2004 19:26:08 -0000
@@ -292,12 +292,12 @@
 					char endc;
 					char *str, *end;
 
+					sp = varname - 2; /* restore sp */
 					end = (char *) wdscan(sp, CSUBST);
 					/* ({) the } or x is already skipped */
 					endc = *end;
 					*end = EOS;
-					str = snptreef((char *) 0, 64, "%S",
-							varname - 1);
+					str = snptreef(NULL, 64, "%S", sp);
 					*end = endc;
 					errorf("%s: bad substitution", str);
 				}
@@ -808,6 +808,7 @@
 			  case '=':	/* can't assign to a vector */
 			  case '%':	/* can't trim a vector (yet) */
 			  case '#':
+			  case '?':
 				return -1;
 			}
 			XPinit(wv, 32);
Index: bin/ksh/exec.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/exec.c,v
retrieving revision 1.31
diff -u -r1.31 exec.c
--- bin/ksh/exec.c	15 Dec 2003 05:25:52 -0000	1.31
+++ bin/ksh/exec.c	10 Dec 2004 19:26:07 -0000
@@ -213,7 +213,7 @@
 		i = ksh_sigsetjmp(e->jbuf, 0);
 		if (i) {
 			sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-			quitenv();
+			quitenv(NULL);
 			unwind(i);
 			/*NOTREACHED*/
 		}
@@ -319,7 +319,7 @@
 			if ((e->flags&EF_BRKCONT_PASS)
 			    || (i != LBREAK && i != LCONTIN))
 			{
-				quitenv();
+				quitenv(NULL);
 				unwind(i);
 			} else if (i == LBREAK) {
 				rv = 0;
@@ -359,7 +359,7 @@
 			if ((e->flags&EF_BRKCONT_PASS)
 			    || (i != LBREAK && i != LCONTIN))
 			{
-				quitenv();
+				quitenv(NULL);
 				unwind(i);
 			} else if (i == LBREAK) {
 				rv = 0;
@@ -429,7 +429,7 @@
     Break:
 	exstat = rv;
 
-	quitenv();		/* restores IO */
+	quitenv(NULL);		/* restores IO */
 	if ((flags&XEXEC))
 		unwind(LEXIT);	/* exit child */
 	if (rv != 0 && !(flags & XERROK)) {
@@ -688,11 +688,11 @@
 		  case LEXIT:
 		  case LLEAVE:
 		  case LSHELL:
-			quitenv();
+			quitenv(NULL);
 			unwind(i);
 			/*NOTREACHED*/
 		  default:
-			quitenv();
+			quitenv(NULL);
 			internal_errorf(1, "CFUNC %d", i);
 		}
 		break;
@@ -1471,8 +1471,7 @@
 	i = ksh_sigsetjmp(e->jbuf, 0);
 	if (i) {
 		source = osource;
-		quitenv();
-		shf_close(shf);	/* after quitenv */
+		quitenv(shf);
 		close(fd);
 		return -2; /* special to iosetup(): don't print error */
 	}
@@ -1488,7 +1487,7 @@
 	} else
 		shf_puts(content, shf);
 
-	quitenv();
+	quitenv(NULL);
 
 	if (shf_close(shf) == EOF) {
 		close(fd);
Index: bin/ksh/expr.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/expr.c,v
retrieving revision 1.9
diff -u -r1.9 expr.c
--- bin/ksh/expr.c	22 Oct 2003 07:40:38 -0000	1.9
+++ bin/ksh/expr.c	10 Dec 2004 19:26:07 -0000
@@ -183,7 +183,7 @@
 		/* Clear EXPRINEVAL in of any variables we were playing with */
 		if (curstate.evaling)
 			curstate.evaling->flag &= ~EXPRINEVAL;
-		quitenv();
+		quitenv(NULL);
 		if (i == LAEXPR) {
 			if (error_ok == KSH_RETURN_ERROR)
 				return 0;
@@ -211,7 +211,7 @@
 		/* can fail if readonly */
 		setstr(vp, str_val(v), error_ok);
 
-	quitenv();
+	quitenv(NULL);
 
 	return 1;
 }
Index: bin/ksh/lex.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/lex.c,v
retrieving revision 1.22
diff -u -r1.22 lex.c
--- bin/ksh/lex.c	10 Nov 2004 21:13:54 -0000	1.22
+++ bin/ksh/lex.c	10 Dec 2004 19:26:07 -0000
@@ -1142,7 +1142,7 @@
 			} else
 				prompt = str_save(substitute(ps1, 0),
 						 saved_atemp);
-			quitenv();
+			quitenv(NULL);
 		}
 #else /* KSH */
 		prompt = str_val(global("PS1"));
Index: bin/ksh/main.c
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/main.c,v
retrieving revision 1.28
diff -u -r1.28 main.c
--- bin/ksh/main.c	23 Aug 2004 14:56:32 -0000	1.28
+++ bin/ksh/main.c	10 Dec 2004 19:26:07 -0000
@@ -475,9 +475,7 @@
 	newenv(E_INCL);
 	i = ksh_sigsetjmp(e->jbuf, 0);
 	if (i) {
-		if (s) /* Do this before quitenv(), which frees the memory */
-			shf_close(s->u.shf);
-		quitenv();
+		quitenv(s ? s->u.shf : NULL);
 		if (old_argv) {
 			e->loc->argv = old_argv;
 			e->loc->argc = old_argc;
@@ -511,8 +509,7 @@
 	s->u.shf = shf;
 	s->file = str_save(name, ATEMP);
 	i = shell(s, FALSE);
-	shf_close(s->u.shf);
-	quitenv();
+	quitenv(s->u.shf);
 	if (old_argv) {
 		e->loc->argv = old_argv;
 		e->loc->argc = old_argc;
@@ -579,12 +576,12 @@
 		  case LLEAVE:
 		  case LRETURN:
 			source = old_source;
-			quitenv();
+			quitenv(NULL);
 			unwind(i);	/* keep on going */
 			/*NOREACHED*/
 		  default:
 			source = old_source;
-			quitenv();
+			quitenv(NULL);
 			internal_errorf(1, "shell: %d", i);
 			/*NOREACHED*/
 		}
@@ -639,7 +636,7 @@
 
 		reclaim();
 	}
-	quitenv();
+	quitenv(NULL);
 	source = old_source;
 	return exstat;
 }
@@ -675,7 +672,7 @@
 			/* Fall through... */
 
 		  default:
-			quitenv();
+			quitenv(NULL);
 		}
 	}
 }
@@ -698,7 +695,7 @@
 }
 
 void
-quitenv()
+quitenv(struct shf *shf)
 {
 	register struct env *ep = e;
 	register int fd;
@@ -713,7 +710,6 @@
 		if (ep->savefd[2]) /* Clear any write errors */
 			shf_reopen(2, SHF_WR, shl_out);
 	}
-	reclaim();
 
 	/* Bottom of the stack.
 	 * Either main shell is exiting or cleanup_parents_env() was called.
@@ -742,8 +738,14 @@
 			chmem_allfree();
 #endif /* MEM_DEBUG */
 		}
+		if (shf)
+			shf_close(shf);
+		reclaim();
 		exit(exstat);
 	}
+	if (shf)
+		shf_close(shf);
+	reclaim();
 
 	e = e->oenv;
 	afree(ep, ATEMP);
Index: bin/ksh/proto.h
===================================================================
RCS file: /home/cvs/openbsd/src/bin/ksh/proto.h,v
retrieving revision 1.12
diff -u -r1.12 proto.h
--- bin/ksh/proto.h	4 Nov 2004 19:20:07 -0000	1.12
+++ bin/ksh/proto.h	10 Dec 2004 19:26:07 -0000
@@ -173,7 +173,7 @@
 int 	shell		ARGS((Source *volatile s, int volatile toplevel));
 void 	unwind		ARGS((int i)) GCC_FUNC_ATTR(noreturn);
 void 	newenv		ARGS((int type));
-void 	quitenv		ARGS((void));
+void 	quitenv		ARGS((struct shf *));
 void	cleanup_parents_env ARGS((void));
 void	cleanup_proc_env ARGS((void));
 void 	aerror		ARGS((Area *ap, const char *msg))



Visit your host, monkey.org