1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Fix KEYBD trap crash when inputting a command substitution (#355)

This change fixes a crash that can occur after setting a KEYBD trap
then inputting a multi-line command substitution. The crash is
similar to issue #347, but it's easier to reproduce since it
doesn't require you to setup a kshrc file. Reproducer for the
crash:

  $ ENV=/./dev/null ksh
  $ trap : KEYBD
  $ : $(
  > true)
  Memory fault(coredump)

The bugfix was backported (with considerable changes) from ksh93v-
2013-10-08. The crash was first reported on the old mailing list:
https://www.mail-archive.com/ast-users@lists.research.att.com/msg00313.html

src/cmd/ksh93/{include/shlex.h,sh/lex.c}:
- To fix this properly, we need sizeof(Lex_t) to work as expected
  in edit.c, but that is thwarted by the _SHLEX_PRIVATE macro in
  lex.c which shlex.h uses to add private structs to the Lex_t type
  in lex.c only. So get rid of that _SHLEX_PRIVATE macro and make
  those members part of the centrally defined struct, renaming them
  to make it clear they're considered private to lex.c.

src/cmd/ksh93/edit/edit.c:
- Now that we can get its size, save and restore the shell lexing
  context when a KEYBD trap is present.

src/cmd/ksh93/tests/pty.sh:
- Add a regression test for the KEYBD trap crash.

Co-authored-by: Martijn Dekker <martijn@inlv.org>
This commit is contained in:
Johnothan King 2021-11-29 19:26:53 -08:00 committed by Martijn Dekker
parent bfad44e56d
commit 370440473e
5 changed files with 70 additions and 52 deletions

View file

@ -45,6 +45,7 @@
#include "test.h"
#include "lexstates.h"
#include "io.h"
#include "shlex.h"
#define TEST_RE 3
#define SYNBAD 3 /* exit value for syntax errors */
@ -68,53 +69,6 @@ local_iswblank(wchar_t wc)
#endif
/*
* This structure allows for arbitrary depth nesting of (...), {...}, [...]
*/
struct lexstate
{
char incase; /* 1 for case pattern, 2 after case */
char intest; /* 1 inside [[ ... ]] */
char testop1; /* 1 when unary test op legal */
char testop2; /* 1 when binary test op legal */
char reservok; /* >0 for reserved word legal */
char skipword; /* next word can't be reserved */
char last_quote; /* last multi-line quote character */
char nestedbrace; /* ${var op {...}} */
};
struct lexdata
{
char nocopy;
char paren;
char dolparen;
char nest;
char docword;
char nested_tilde;
char *docend;
char noarg;
char warn;
char message;
char arith;
char *first;
int level;
int lastc;
int lex_max;
int *lex_match;
int lex_state;
int docextra;
#if SHOPT_KIA
off_t kiaoff;
#endif
};
#define _SHLEX_PRIVATE \
struct lexdata lexd; \
struct lexstate lex;
#include "shlex.h"
#define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
@ -1542,7 +1496,7 @@ static int comsub(register Lex_t *lp, int endtok)
struct ionod *inheredoc = lp->heredoc;
char *first,*cp=fcseek(0),word[5];
int off, messages=0, assignok=lp->assignok, csub;
struct lexstate save;
struct _shlex_pvt_lexstate_ save;
save = lp->lex;
csub = lp->comsub;
sh_lexopen(lp,lp->sh,1);