1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-13 11:42:21 +00:00

lex.c: prevent restoring outdated stack pointer

Lexical levels are stored in a dynamically grown array of int values
grown by the stack_grow function. The pointer lex_match and the
maximum index lex_max are part of the lexer state struct that is now
saved and restored in various places -- see e.g. 37044047, a2bc49be.
If the stack needs to be grown, it is reallocated in stack_grow()
using sh_realloc(). If that happens between saving and restoring the
lexer state, then an outdated pointer is restored, and crash.

src/cmd/ksh93/include/shlex.h,
src/cmd/ksh93/sh/lex.c:
- Take lex_match and lex_max out of the lexer state struct and make
  them separate static variables.

src/cmd/ksh93/edit/edit.c:
- While we're at it, save and restore the lexer state in a way that
  is saner than the 93v- beta approach (re: 37044047) as well as
  more readable. Instead of permanently allocating memory, use a
  local variable to save the struct. Save/restore directly around
  the sh_trap() call that actually needs this done.

Resolves: https://github.com/ksh93/ksh/issues/482
This commit is contained in:
Martijn Dekker 2022-06-23 02:56:18 +01:00
parent d8dc2a1d81
commit da97587e9e
4 changed files with 17 additions and 20 deletions

2
NEWS
View file

@ -8,6 +8,8 @@ Any uppercase BUG_* names are modernish shell bug IDs.
- Fixed: 'echo' failed when used inside a command substitution that - Fixed: 'echo' failed when used inside a command substitution that
is inside a nested compound assignment. is inside a nested compound assignment.
- Fixed a crash in KEYBD trap handling introduced on 2021-11-29.
2022-06-20: 2022-06-20:
- Fixed a race condition that could cause redirections to fail with a - Fixed a race condition that could cause redirections to fail with a

View file

@ -50,7 +50,6 @@
static char CURSOR_UP[20] = { ESC, '[', 'A', 0 }; static char CURSOR_UP[20] = { ESC, '[', 'A', 0 };
static char KILL_LINE[20] = { ESC, '[', 'J', 0 }; static char KILL_LINE[20] = { ESC, '[', 'J', 0 };
static Lex_t *savelex;
#if SHOPT_MULTIBYTE #if SHOPT_MULTIBYTE
@ -219,8 +218,6 @@ int tty_set(int fd, int action, struct termios *tty)
void tty_cooked(register int fd) void tty_cooked(register int fd)
{ {
register Edit_t *ep = (Edit_t*)(sh.ed_context); register Edit_t *ep = (Edit_t*)(sh.ed_context);
if(sh.st.trap[SH_KEYTRAP] && savelex)
memcpy(sh.lex_context,savelex,sizeof(Lex_t));
ep->e_keytrap = 0; ep->e_keytrap = 0;
if(ep->e_raw==0) if(ep->e_raw==0)
return; return;
@ -842,12 +839,6 @@ void ed_setup(register Edit_t *ep, int fd, int reedit)
ep->e_lbuf[n] = *pp++; ep->e_lbuf[n] = *pp++;
ep->e_default = 0; ep->e_default = 0;
} }
if(sh.st.trap[SH_KEYTRAP])
{
if(!savelex)
savelex = (Lex_t*)sh_malloc(sizeof(Lex_t));
memcpy(savelex, sh.lex_context, sizeof(Lex_t));
}
} }
#endif /* SHOPT_ESH || SHOPT_VSH */ #endif /* SHOPT_ESH || SHOPT_VSH */
@ -1637,6 +1628,7 @@ static int keytrap(Edit_t *ep,char *inbuff,register int insize, int bufsize, int
{ {
register char *cp; register char *cp;
int savexit; int savexit;
Lex_t *lexp = (Lex_t*)sh.lex_context, savelex;
#if SHOPT_MULTIBYTE #if SHOPT_MULTIBYTE
char buff[MAXLINE]; char buff[MAXLINE];
ed_external(ep->e_inbuf,cp=buff); ed_external(ep->e_inbuf,cp=buff);
@ -1657,7 +1649,9 @@ static int keytrap(Edit_t *ep,char *inbuff,register int insize, int bufsize, int
nv_putval(ED_TXTNOD,(char*)cp,NV_NOFREE); nv_putval(ED_TXTNOD,(char*)cp,NV_NOFREE);
nv_putval(ED_MODENOD,ep->e_vi_insert,NV_NOFREE); nv_putval(ED_MODENOD,ep->e_vi_insert,NV_NOFREE);
savexit = sh.savexit; savexit = sh.savexit;
savelex = *lexp;
sh_trap(sh.st.trap[SH_KEYTRAP],0); sh_trap(sh.st.trap[SH_KEYTRAP],0);
*lexp = savelex;
sh.savexit = savexit; sh.savexit = savexit;
if((cp = nv_getval(ED_CHRNOD)) == inbuff) if((cp = nv_getval(ED_CHRNOD)) == inbuff)
nv_unset(ED_CHRNOD); nv_unset(ED_CHRNOD);

View file

@ -61,8 +61,6 @@ struct _shlex_pvt_lexdata_
char *first; char *first;
int level; int level;
int lastc; int lastc;
int lex_max;
int *lex_match;
int lex_state; int lex_state;
int docextra; int docextra;
#if SHOPT_KIA #if SHOPT_KIA

View file

@ -62,13 +62,13 @@ local_iswblank(wchar_t wc)
#endif #endif
#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\ #define pushlevel(lp,c,s) ((lp->lexd.level>=lex_max?stack_grow():1) &&\
((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\ ((lex_match[lp->lexd.level++]=lp->lexd.lastc),\
lp->lexd.lastc=(((s)<<CHAR_BIT)|(c)))) lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
#define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT) #define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT)
#define endchar(lp) (lp->lexd.lastc&0xff) #define endchar(lp) (lp->lexd.lastc&0xff)
#define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c))) #define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
#define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level]) #define poplevel(lp) (lp->lexd.lastc=lex_match[--lp->lexd.level])
static char *fmttoken(Lex_t*, int); static char *fmttoken(Lex_t*, int);
static struct argnod *endword(int); static struct argnod *endword(int);
@ -77,9 +77,12 @@ static void setupalias(Lex_t*,const char*, Namval_t*);
static int comsub(Lex_t*,int); static int comsub(Lex_t*,int);
static void nested_here(Lex_t*); static void nested_here(Lex_t*);
static int here_copy(Lex_t*, struct ionod*); static int here_copy(Lex_t*, struct ionod*);
static int stack_grow(Lex_t*); static int stack_grow(void);
static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL }; static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
/* these were taken out of the Lex_t struct because they should never be saved and restored (see stack_grow()) */
static int lex_max, *lex_match;
#if SHOPT_KIA #if SHOPT_KIA
static void refvar(Lex_t *lp, int type) static void refvar(Lex_t *lp, int type)
@ -2472,12 +2475,12 @@ static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
/* /*
* grow storage stack for nested constructs by STACK_ARRAY * grow storage stack for nested constructs by STACK_ARRAY
*/ */
static int stack_grow(Lex_t *lp) static int stack_grow(void)
{ {
lp->lexd.lex_max += STACK_ARRAY; lex_max += STACK_ARRAY;
if(lp->lexd.lex_match) if(lex_match)
lp->lexd.lex_match = (int*)sh_realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max); lex_match = (int*)sh_realloc((char*)lex_match,sizeof(int)*lex_max);
else else
lp->lexd.lex_match = (int*)sh_malloc(sizeof(int)*STACK_ARRAY); lex_match = (int*)sh_malloc(sizeof(int)*STACK_ARRAY);
return(1); return(1);
} }