Fix apparent programming mistake (newblock doesn’t imply newenv)

that caused “echo ${|true;}$(true)” to segfault; problem reported
by pshevtsov and wbx@ in IRC (thanks!); fix sponsored by tarent
This commit is contained in:
tg 2013-07-24 12:39:28 +00:00
parent 4bee63495a
commit e495fde858
2 changed files with 15 additions and 20 deletions

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.619 2013/07/21 18:47:16 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.620 2013/07/24 12:39:25 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -10186,12 +10186,15 @@ stdin:
# ensure trailing newlines are kept # ensure trailing newlines are kept
t=${|REPLY=$'foo\n\n';} t=${|REPLY=$'foo\n\n';}
typeset -p t typeset -p t
echo -n this used to segfault
echo ${|true;}$(true).
expected-stdout: expected-stdout:
before: x<1> y<2> z<3> R<4> before: x<1> y<2> z<3> R<4>
begin: x<1> y<> z<3> R<> begin: x<1> y<> z<3> R<>
end: x<5> y<6> z<7> R<8> end: x<5> y<6> z<7> R<8>
after: x<8> y<2> z<7> R<4> after: x<8> y<2> z<7> R<4>
typeset t=$'foo\n\n' typeset t=$'foo\n\n'
this used to segfault.
--- ---
name: test-stnze-1 name: test-stnze-1
description: description:

30
eval.c
View File

@ -23,7 +23,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.140 2013/07/21 18:36:00 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/eval.c,v 1.141 2013/07/24 12:39:28 tg Exp $");
/* /*
* string expansion * string expansion
@ -65,7 +65,6 @@ typedef struct {
static int varsub(Expand *, const char *, const char *, int *, int *); static int varsub(Expand *, const char *, const char *, int *, int *);
static int comsub(Expand *, const char *, int); static int comsub(Expand *, const char *, int);
static void funsub(struct op *);
static char *valsub(struct op *, Area *); static char *valsub(struct op *, Area *);
static char *trimsub(char *, char *, int); static char *trimsub(char *, char *, int);
static void glob(char *, XPtrV *, bool); static void glob(char *, XPtrV *, bool);
@ -1368,7 +1367,7 @@ comsub(Expand *xp, const char *cp, int fn MKSH_A_UNUSED)
* run tree, with output thrown into the tempfile, * run tree, with output thrown into the tempfile,
* in a new function block * in a new function block
*/ */
funsub(t); valsub(t, NULL);
subst_exstat = exstat & 0xFF; subst_exstat = exstat & 0xFF;
/* rewind the tempfile and restore regular stdout */ /* rewind the tempfile and restore regular stdout */
lseek(shf_fileno(shf), (off_t)0, SEEK_SET); lseek(shf_fileno(shf), (off_t)0, SEEK_SET);
@ -1834,28 +1833,21 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
} }
/* helper function due to setjmp/longjmp woes */ /* helper function due to setjmp/longjmp woes */
static void
funsub(struct op *t)
{
newblock();
e->type = E_FUNC;
if (!kshsetjmp(e->jbuf))
execute(t, XXCOM | XERROK, NULL);
popblock();
}
static char * static char *
valsub(struct op *t, Area *ap) valsub(struct op *t, Area *ap)
{ {
char *cp; char *cp = NULL;
struct tbl *vp; struct tbl * volatile vp = NULL;
newenv(E_FUNC);
newblock(); newblock();
vp = local("REPLY", false); if (ap)
e->type = E_FUNC; vp = local("REPLY", false);
if (!kshsetjmp(e->jbuf)) if (!kshsetjmp(e->jbuf))
execute(t, XXCOM | XERROK, NULL); execute(t, XXCOM | XERROK, NULL);
strdupx(cp, str_val(vp), ap); if (vp)
popblock(); strdupx(cp, str_val(vp), ap);
quitenv(NULL);
return (cp); return (cp);
} }