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