1fded4
From 4604df9ada906e0a6537157a63b6ce7c0509f34d Mon Sep 17 00:00:00 2001
1fded4
From: Martijn Dekker <martijn@inlv.org>
1fded4
Date: Thu, 28 Jan 2021 06:08:38 +0000
1fded4
Subject: [PATCH] Stack robustness fixes from OpenSUSE
1fded4
1fded4
Three OpenSUSE patches from:
1fded4
https://build.opensuse.org/package/show/shells/ksh
1fded4
1fded4
As usual, the relevant bug is not currently public:
1fded4
https://bugzilla.opensuse.org/show_bug.cgi?id=844071
1fded4
1fded4
src/cmd/ksh93/sh/xec.c: sh_debug()/sh_exec():
1fded4
- Fix stk restoration. [bnc#844071]
1fded4
1fded4
src/lib/libast/misc/stk.c:
1fded4
- Fix stk aliasing code. [bnc#844071]
1fded4
  (ksh93-stkalias.dif)
1fded4
- Make a unknown location fatal in stkset() so that we get a core
1fded4
  dump right away instead of later in an unrelated part of code.
1fded4
  (ksh93-stkset-abort.dif)
1fded4
1fded4
src/lib/libast/man/stk.3,
1fded4
src/lib/libast/man/stak.3:
1fded4
- Update manual with new stkset() behaviour. (93u+m addition)
1fded4
  (Note that stak is implemented as macros that translate to stk)
1fded4
---
1fded4
 src/cmd/ksh93/sh/xec.c    |  6 +++---
1fded4
 src/lib/libast/man/stak.3 |  5 +++--
1fded4
 src/lib/libast/man/stk.3  |  5 +++--
1fded4
 src/lib/libast/misc/stk.c | 16 ++++++++++------
1fded4
 4 files changed, 19 insertions(+), 13 deletions(-)
1fded4
1fded4
diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c
1fded4
index 23526098ec20..ca3876394d63 100644
1fded4
--- a/src/cmd/ksh93/sh/xec.c
1fded4
+++ b/src/cmd/ksh93/sh/xec.c
1fded4
@@ -646,8 +646,8 @@ int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subsc
1fded4
 	Stk_t			*stkp=shp->stk;
1fded4
 	struct sh_scoped	savst;
1fded4
 	Namval_t		*np = SH_COMMANDNOD;
1fded4
-	char			*sav = stkptr(stkp,0);
1fded4
 	int			n=4, offset=stktell(stkp);
1fded4
+	char			*sav = stkfreeze(stkp,0);
1fded4
 	const char		*cp = "+=( ";
1fded4
 	Sfio_t			*iop = stkstd;
1fded4
 	short			level;
1fded4
@@ -702,7 +702,7 @@ int sh_debug(Shell_t *shp, const char *trap, const char *name, const char *subsc
1fded4
 	nv_putval(SH_FUNNAMENOD,shp->st.funname,NV_NOFREE);
1fded4
 	shp->st = savst;
1fded4
 	if(sav != stkptr(stkp,0))
1fded4
-		stkset(stkp,sav,0);
1fded4
+		stkset(stkp,sav,offset);
1fded4
 	else
1fded4
 		stkseek(stkp,offset);
1fded4
 	return(n);
1fded4
@@ -962,7 +962,7 @@ int sh_exec(register const Shnode_t *t, int flags)
1fded4
 		int		ntflag = 0;
1fded4
 #endif
1fded4
 		int		topfd = shp->topfd;
1fded4
-		char 		*sav=stkptr(stkp,0);
1fded4
+		char 		*sav=stkfreeze(stkp,0);
1fded4
 		char		*cp=0, **com=0, *comn;
1fded4
 		int		argn;
1fded4
 		int 		skipexitset = 0;
1fded4
diff --git a/src/lib/libast/man/stak.3 b/src/lib/libast/man/stak.3
1fded4
index 5feac69..89e0f54 100644
1fded4
--- a/src/lib/libast/man/stak.3
1fded4
+++ b/src/lib/libast/man/stak.3
1fded4
@@ -109,8 +109,9 @@ the given \fIaddress\fP, and sets the current object to the given
1fded4
 \fIaddress\fP.
1fded4
 The top of the current object is set to \fIoffset\fP bytes from
1fded4
 current object.
1fded4
-If \fIaddress\fP is not the address of an object on the
1fded4
-stack the result is undefined.
1fded4
+If \fIaddress\fP is null, the stack is reset to the beginning.
1fded4
+If it is non-null, but is not the address of an object on the
1fded4
+stack, the program aborts and dumps core.
1fded4
 .PP
1fded4
 The remaining functions are used to build the current object incrementally.
1fded4
 An object that is built incrementally on the stack will  
1fded4
diff --git a/src/lib/libast/man/stk.3 b/src/lib/libast/man/stk.3
1fded4
index 20dfdbefa44c..dd5705cf1188 100644
1fded4
--- a/src/lib/libast/man/stk.3
1fded4
+++ b/src/lib/libast/man/stk.3
1fded4
@@ -110,8 +110,9 @@ the given \fIaddress\fP, and sets the current object to the given
1fded4
 \fIaddress\fP.
1fded4
 The top of the current object is set to \fIoffset\fP bytes from
1fded4
 current object.
1fded4
-If \fIaddress\fP is not the address of an object on the
1fded4
-stack the result is undefined.
1fded4
+If \fIaddress\fP is null, the stack is reset to the beginning.
1fded4
+If it is non-null, but is not the address of an object on the
1fded4
+stack, the program aborts and dumps core.
1fded4
 .PP
1fded4
 The \f5sfio\fP(3) output functions can be used to build
1fded4
 current object incrementally.
1fded4
diff --git a/src/lib/libast/misc/stk.c b/src/lib/libast/misc/stk.c
1fded4
index 31cd0911dd29..f147ae4fec8c 100644
1fded4
--- a/src/lib/libast/misc/stk.c
1fded4
+++ b/src/lib/libast/misc/stk.c
1fded4
@@ -331,9 +331,9 @@ int stkon(register Sfio_t * stream, register char* loc)
1fded4
 }
1fded4
 /*
1fded4
  * reset the bottom of the current stack back to <loc>
1fded4
- * if <loc> is not in this stack, then the stack is reset to the beginning
1fded4
+ * if <loc> is null, then the stack is reset to the beginning
1fded4
+ * if <loc> is not in this stack, the program dumps core
1fded4
  * otherwise, the top of the stack is set to stkbot+<offset>
1fded4
- *
1fded4
  */
1fded4
 char *stkset(register Sfio_t * stream, register char* loc, size_t offset)
1fded4
 {
1fded4
@@ -377,6 +377,9 @@ char *stkset(register Sfio_t * stream, register char* loc, size_t offset)
1fded4
 			break;
1fded4
 		frames++;
1fded4
 	}
1fded4
+	/* not found: produce a useful stack trace now instead of a useless one later */
1fded4
+	if(loc)
1fded4
+		abort();
1fded4
 	/* set stack back to the beginning */
1fded4
 	cp = (char*)(fp+1);
1fded4
 	if(frames)
1fded4
@@ -503,7 +506,7 @@ static char *stkgrow(register Sfio_t *stream, size_t size)
1fded4
 	register char *cp, *dp=0;
1fded4
 	register size_t m = stktell(stream);
1fded4
 	size_t endoff;
1fded4
-	char *end=0;
1fded4
+	char *end=0, *oldbase=0;
1fded4
 	int nn=0,add=1;
1fded4
 	n += (m + sizeof(struct frame)+1);
1fded4
 	if(sp->stkflags&STK_SMALL)
1fded4
@@ -519,6 +522,7 @@ static char *stkgrow(register Sfio_t *stream, size_t size)
1fded4
 		dp=sp->stkbase;
1fded4
 		sp->stkbase = ((struct frame*)dp)->prev;
1fded4
 		end = fp->end;
1fded4
+		oldbase = dp;
1fded4
 	}
1fded4
 	endoff = end - dp;
1fded4
 	cp = newof(dp, char, n, nn*sizeof(char*));
1fded4
@@ -545,10 +549,10 @@ static char *stkgrow(register Sfio_t *stream, size_t size)
1fded4
 	if(fp->nalias=nn)
1fded4
 	{
1fded4
 		fp->aliases = (char**)fp->end;
1fded4
-		if(end && nn>1)
1fded4
-			memmove(fp->aliases,end,(nn-1)*sizeof(char*));
1fded4
+		if(end && nn>add)
1fded4
+			memmove(fp->aliases,end,(nn-add)*sizeof(char*));
1fded4
 		if(add)
1fded4
-			fp->aliases[nn-1] = dp + roundof(sizeof(struct frame),STK_ALIGN);
1fded4
+			fp->aliases[nn-1] = oldbase + roundof(sizeof(struct frame),STK_ALIGN);
1fded4
 	}
1fded4
 	if(m && !dp)
1fded4
 	{