This is a combination of official patches 1 and 2 and a patch I got from
Debian to fix a memory allocation problem.

diff -ur ./pdksh-5.2.14-orig/alloc.c ./pdksh-5.2.14/alloc.c
--- ./pdksh-5.2.14-orig/alloc.c	1999-05-18 10:44:47.000000000 -0400
+++ ./pdksh-5.2.14/alloc.c	2003-03-05 15:25:50.000000000 -0500
@@ -110,6 +110,7 @@
 	Block  *block;
 	struct {int _;} junk;	/* alignment */
 	double djunk;		/* alignment */
+	char   ajunk[16];       /* alignment */
 };
 
 struct Block {
@@ -282,7 +283,9 @@
 	 * working (as it assumes size < ICELLS means it is not
 	 * a `large object').
 	 */
-	if (oldcells > ICELLS && cells > ICELLS) {
+	if (oldcells > ICELLS && cells > ICELLS
+	    && ((dp-2)->block->last == dp+oldcells) /* don't destroy blocks which have grown! */
+	    ) {
 		Block *bp = (dp-2)->block;
 		Block *nbp;
 		/* Saved in case realloc fails.. */
@@ -409,17 +412,19 @@
 		aerror(ap, "freeing null pointer");
 	bp = (dp-2)->block;
 
+	if (dp < &bp->cell[NOBJECT_FIELDS] || dp >= bp->last)
+		aerror(ap, "freeing memory outside of block (corrupted?)");
+
 	/* If this is a large object, just free it up... */
 	/* Release object... */
-	if ((dp-1)->size > ICELLS) {
+	if ((dp-1)->size > ICELLS
+	    && (bp->last == dp + (dp-1)->size) /* don't free non-free blocks which have grown! */
+	    ) {
 		ablockfree(bp, ap);
 		ACHECK(ap);
 		return;
 	}
 
-	if (dp < &bp->cell[NOBJECT_FIELDS] || dp >= bp->last)
-		aerror(ap, "freeing memory outside of block (corrupted?)");
-
 	/* find position in free list */
 	/* XXX if we had prev/next pointers for objects, this loop could go */
 	for (fpp = NULL, fp = bp->freelist; fp < dp; fpp = fp, fp = fp->next)
diff -ur ./pdksh-5.2.14-orig/exec.c ./pdksh-5.2.14/exec.c
--- ./pdksh-5.2.14-orig/exec.c	2001-12-03 12:39:34.000000000 -0500
+++ ./pdksh-5.2.14/exec.c	2003-03-05 15:25:44.000000000 -0500
@@ -76,7 +76,6 @@
 {
 	int i;
 	volatile int rv = 0;
-	volatile int rv_prop = 0; /* rv being propogated or newly generated? */
 	int pv[2];
 	char ** volatile ap;
 	char *s, *cp;
@@ -158,7 +157,6 @@
 
 	  case TPAREN:
 		rv = execute(t->left, flags|XFORK);
-		rv_prop = 1;
 		break;
 
 	  case TPIPE:
@@ -277,7 +275,6 @@
 			rv = execute(t->right, flags & XERROK);
 		else
 			flags |= XERROK;
-		rv_prop = 1;
 		break;
 
 	  case TBANG:
@@ -326,7 +323,6 @@
 			}
 		}
 		rv = 0; /* in case of a continue */
-		rv_prop = 1;
 		if (t->type == TFOR) {
 			while (*ap != NULL) {
 				setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
@@ -338,7 +334,6 @@
 			for (;;) {
 				if (!(cp = do_selectargs(ap, is_first))) {
 					rv = 1;
-					rv_prop = 0;
 					break;
 				}
 				is_first = FALSE;
@@ -370,7 +365,6 @@
 		rv = 0; /* in case of a continue */
 		while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE))
 			rv = execute(t->right, flags & XERROK);
-		rv_prop = 1;
 		break;
 
 	  case TIF:
@@ -380,7 +374,6 @@
 		rv = execute(t->left, XERROK) == 0 ?
 			execute(t->right->left, flags & XERROK) :
 			execute(t->right->right, flags & XERROK);
-		rv_prop = 1;
 		break;
 
 	  case TCASE:
@@ -393,12 +386,10 @@
 		break;
 	  Found:
 		rv = execute(t->left, flags & XERROK);
-		rv_prop = 1;
 		break;
 
 	  case TBRACE:
 		rv = execute(t->left, flags & XERROK);
-		rv_prop = 1;
 		break;
 
 	  case TFUNCT:
@@ -410,7 +401,6 @@
 		 * (allows "ls -l | time grep foo").
 		 */
 		rv = timex(t, flags & ~XEXEC);
-		rv_prop = 1;
 		break;
 
 	  case TEXEC:		/* an eval'd TCOM */
@@ -438,7 +428,7 @@
 	quitenv();		/* restores IO */
 	if ((flags&XEXEC))
 		unwind(LEXIT);	/* exit child */
-	if (rv != 0 && !rv_prop && !(flags & XERROK)) {
+	if (rv != 0 && !(flags & XERROK)) {
 		if (Flag(FERREXIT))
 			unwind(LERROR);
 		trapsig(SIGERR_);
diff -ur ./pdksh-5.2.14-orig/exec.c.orig ./pdksh-5.2.14/exec.c.orig
--- ./pdksh-5.2.14-orig/exec.c.orig	1999-07-13 12:53:24.000000000 -0400
+++ ./pdksh-5.2.14/exec.c.orig	2001-12-03 12:39:34.000000000 -0500
@@ -76,6 +76,7 @@
 {
 	int i;
 	volatile int rv = 0;
+	volatile int rv_prop = 0; /* rv being propogated or newly generated? */
 	int pv[2];
 	char ** volatile ap;
 	char *s, *cp;
@@ -157,6 +158,7 @@
 
 	  case TPAREN:
 		rv = execute(t->left, flags|XFORK);
+		rv_prop = 1;
 		break;
 
 	  case TPIPE:
@@ -275,6 +277,7 @@
 			rv = execute(t->right, flags & XERROK);
 		else
 			flags |= XERROK;
+		rv_prop = 1;
 		break;
 
 	  case TBANG:
@@ -323,6 +326,7 @@
 			}
 		}
 		rv = 0; /* in case of a continue */
+		rv_prop = 1;
 		if (t->type == TFOR) {
 			while (*ap != NULL) {
 				setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
@@ -334,6 +338,7 @@
 			for (;;) {
 				if (!(cp = do_selectargs(ap, is_first))) {
 					rv = 1;
+					rv_prop = 0;
 					break;
 				}
 				is_first = FALSE;
@@ -365,6 +370,7 @@
 		rv = 0; /* in case of a continue */
 		while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE))
 			rv = execute(t->right, flags & XERROK);
+		rv_prop = 1;
 		break;
 
 	  case TIF:
@@ -374,6 +380,7 @@
 		rv = execute(t->left, XERROK) == 0 ?
 			execute(t->right->left, flags & XERROK) :
 			execute(t->right->right, flags & XERROK);
+		rv_prop = 1;
 		break;
 
 	  case TCASE:
@@ -386,10 +393,12 @@
 		break;
 	  Found:
 		rv = execute(t->left, flags & XERROK);
+		rv_prop = 1;
 		break;
 
 	  case TBRACE:
 		rv = execute(t->left, flags & XERROK);
+		rv_prop = 1;
 		break;
 
 	  case TFUNCT:
@@ -401,6 +410,7 @@
 		 * (allows "ls -l | time grep foo").
 		 */
 		rv = timex(t, flags & ~XEXEC);
+		rv_prop = 1;
 		break;
 
 	  case TEXEC:		/* an eval'd TCOM */
@@ -428,7 +438,7 @@
 	quitenv();		/* restores IO */
 	if ((flags&XEXEC))
 		unwind(LEXIT);	/* exit child */
-	if (rv != 0 && !(flags & XERROK)) {
+	if (rv != 0 && !rv_prop && !(flags & XERROK)) {
 		if (Flag(FERREXIT))
 			unwind(LERROR);
 		trapsig(SIGERR_);
diff -ur ./pdksh-5.2.14-orig/jobs.c ./pdksh-5.2.14/jobs.c
--- ./pdksh-5.2.14-orig/jobs.c	2001-12-03 12:39:00.000000000 -0500
+++ ./pdksh-5.2.14/jobs.c	2003-03-05 15:25:43.000000000 -0500
@@ -219,7 +219,8 @@
 static void		check_job ARGS((Job *j));
 static void		put_job ARGS((Job *j, int where));
 static void		remove_job ARGS((Job *j, const char *where));
-static int		kill_job ARGS((Job *j, int sig));
+static void		kill_job ARGS((Job *j));
+static void	 	fill_command ARGS((char *c, int len, struct op *t));
 
 /* initialize job control */
 void
@@ -293,17 +294,10 @@
 				    && procpid == kshpid)))))
 		{
 			killed = 1;
-			if (j->pgrp == 0)
-				kill_job(j, SIGHUP);
-			else
-				killpg(j->pgrp, SIGHUP);
+			killpg(j->pgrp, SIGHUP);
 #ifdef JOBS
-			if (j->state == PSTOPPED) {
-				if (j->pgrp == 0)
-					kill_job(j, SIGCONT);
-				else
-					killpg(j->pgrp, SIGCONT);
-			}
+			if (j->state == PSTOPPED)
+				killpg(j->pgrp, SIGCONT);
 #endif /* JOBS */
 		}
 	}
@@ -503,7 +497,7 @@
 		put_job(j, PJ_PAST_STOPPED);
 	}
 
-	snptreef(p->command, sizeof(p->command), "%T", t);
+	fill_command(p->command, sizeof(p->command), t);
 
 	/* create child process */
 	forksleep = 1;
@@ -514,7 +508,7 @@
 		forksleep <<= 1;
 	}
 	if (i < 0) {
-		kill_job(j, SIGKILL);
+		kill_job(j);
 		remove_job(j, "fork failed");
 #ifdef NEED_PGRP_SYNC
 		if (j_sync_open) {
@@ -829,10 +823,11 @@
 	}
 
 	if (j->pgrp == 0) {	/* started when !Flag(FMONITOR) */
-		if (kill_job(j, sig) < 0) {
-			bi_errorf("%s: %s", cp, strerror(errno));
-			rv = 1;
-		}
+		for (p=j->proc_list; p != (Proc *) 0; p = p->next)
+			if (kill(p->pid, sig) < 0) {
+				bi_errorf("%s: %s", cp, strerror(errno));
+				rv = 1;
+			}
 	} else {
 #ifdef JOBS
 		if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP))
@@ -1830,17 +1825,50 @@
  *
  * If jobs are compiled in then this routine expects sigchld to be blocked.
  */
-static int
-kill_job(j, sig)
+static void
+kill_job(j)
 	Job	*j;
-	int	sig;
 {
 	Proc	*p;
-	int	rval = 0;
 
 	for (p = j->proc_list; p != (Proc *) 0; p = p->next)
 		if (p->pid != 0)
-			if (kill(p->pid, sig) < 0)
-				rval = -1;
-	return rval;
+			(void) kill(p->pid, SIGKILL);
+}
+
+/* put a more useful name on a process than snptreef does (in certain cases) */
+static void
+fill_command(c, len, t)
+	char		*c;
+	int		len;
+	struct op	*t;
+{
+	int		alen;
+	char		**ap;
+
+	if (t->type == TEXEC || t->type == TCOM) {
+		/* Causes problems when set -u is in effect, can also
+		   cause problems when array indices evaluated (may have
+		   side effects, eg, assignment, incr, etc.)
+		if (t->type == TCOM)
+			ap = eval(t->args, DOBLANK|DONTRUNCOMMAND);
+		else
+		*/
+		ap = t->args;
+		--len; /* save room for the null */
+		while (len > 0 && *ap != (char *) 0) {
+			alen = strlen(*ap);
+			if (alen > len)
+				alen = len;
+			memcpy(c, *ap, alen);
+			c += alen;
+			len -= alen;
+			if (len > 0) {
+				*c++ = ' '; len--;
+			}
+			ap++;
+		}
+		*c = '\0';
+	} else
+		snptreef(c, len, "%T", t);
 }
diff -ur ./pdksh-5.2.14-orig/shf.c ./pdksh-5.2.14/shf.c
--- ./pdksh-5.2.14-orig/shf.c	2001-12-03 12:39:00.000000000 -0500
+++ ./pdksh-5.2.14/shf.c	2003-03-05 15:25:43.000000000 -0500
@@ -355,6 +355,7 @@
 		shf->rp = nbuf + (shf->rp - shf->buf);
 		shf->wp = nbuf + (shf->wp - shf->buf);
 		shf->rbsize += shf->wbsize;
+		shf->wbsize += shf->wbsize;
 		shf->wnleft += shf->wbsize;
 		shf->wbsize *= 2;
 		shf->buf = nbuf;
diff -ur ./pdksh-5.2.14-orig/var.c ./pdksh-5.2.14/var.c
--- ./pdksh-5.2.14-orig/var.c	2001-12-03 12:39:00.000000000 -0500
+++ ./pdksh-5.2.14/var.c	2003-03-05 15:25:43.000000000 -0500
@@ -353,9 +353,7 @@
 	const char *s;
 	int error_ok;
 {
-	int no_ro_check = error_ok & 0x4;
-	error_ok &= ~0x4;
-	if ((vq->flag & RDONLY) && !no_ro_check) {
+	if (vq->flag & RDONLY) {
 		warningf(TRUE, "%s: is read only", vq->name);
 		if (!error_ok)
 			errorf(null);
@@ -717,13 +715,13 @@
 	if (val != NULL) {
 		if (vp->flag&INTEGER) {
 			/* do not zero base before assignment */
-			setstr(vp, val, KSH_UNWIND_ERROR | 0x4);
+			setstr(vp, val, KSH_UNWIND_ERROR);
 			/* Done after assignment to override default */
 			if (base > 0)
 				vp->type = base;
 		} else
 			/* setstr can't fail (readonly check already done) */
-			setstr(vp, val, KSH_RETURN_ERROR | 0x4);
+			setstr(vp, val, KSH_RETURN_ERROR);
 	}
 
 	/* only x[0] is ever exported, so use vpbase */

