From 31750795fe13fc0343ade4f2aadb55f20548f628 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Oct 2014 16:29:56 +0100 Subject: 33345: fix anonymous function complex command handling. Longstanding problem caused simple anonymous function incorrectly to reset the overall "complext" state, causing wordcode to be diverted into execsimple(), which caused a crash 'cos ist wasn't simple. --- ChangeLog | 4 ++ Src/parse.c | 167 ++++++++++++++++++++++++++------------------------- Test/C04funcdef.ztst | 4 ++ 3 files changed, 92 insertions(+), 83 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7c658e196..3e273d1ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2014-10-03 Peter Stephenson + * 33345: Src/parse.c, Test/C04funcdef.ztst: fix longstanding + anonoymous function corruption of "complex" state that allowed + complex wordcode to be passed to execsimple(), causing crash. + * unposted: src/parse.c: comments were the wrong way round. * 33343: Src/parse.c, Test/C04funcdef.ztst: variant anonymous diff --git a/Src/parse.c b/Src/parse.c index ad1ba8957..f4ea639d6 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -202,7 +202,7 @@ struct heredocs *hdocs; * sublists is that they can be executed faster, see exec.c. In the * parser, the test if a list can be simplified is done quite simply * by passing a int* around which gets set to non-zero if the thing - * just parsed is `complex', i.e. may need to be run by forking or + * just parsed is `cmplx', i.e. may need to be run by forking or * some such. * * In each of the above, strings are encoded as one word code. For empty @@ -564,9 +564,9 @@ parse_cond(void) /**/ static void -set_list_code(int p, int type, int complex) +set_list_code(int p, int type, int cmplx) { - if (!complex && (type == Z_SYNC || type == (Z_SYNC | Z_END)) && + if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) && WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) { int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE); ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p); @@ -581,9 +581,9 @@ set_list_code(int p, int type, int complex) /**/ static void -set_sublist_code(int p, int type, int flags, int skip, int complex) +set_sublist_code(int p, int type, int flags, int skip, int cmplx) { - if (complex) + if (cmplx) ecbuf[p] = WCB_SUBLIST(type, flags, skip); else { ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip); @@ -597,7 +597,7 @@ set_sublist_code(int p, int type, int flags, int skip, int complex) /**/ static int -par_list(int *complex) +par_list(int *cmplx) { int p, lp = -1, c; @@ -610,10 +610,10 @@ par_list(int *complex) c = 0; if (par_sublist(&c)) { - *complex |= c; + *cmplx |= c; if (tok == SEPER || tok == AMPER || tok == AMPERBANG) { if (tok != SEPER) - *complex = 1; + *cmplx = 1; set_list_code(p, ((tok == SEPER) ? Z_SYNC : (tok == AMPER) ? Z_ASYNC : (Z_ASYNC | Z_DISOWN)), c); @@ -638,13 +638,13 @@ par_list(int *complex) /**/ static int -par_list1(int *complex) +par_list1(int *cmplx) { int p = ecadd(0), c = 0; if (par_sublist(&c)) { set_list_code(p, (Z_SYNC | Z_END), c); - *complex |= c; + *cmplx |= c; return 1; } else { ecused--; @@ -658,7 +658,7 @@ par_list1(int *complex) /**/ static int -par_sublist(int *complex) +par_sublist(int *cmplx) { int f, p, c = 0; @@ -667,7 +667,7 @@ par_sublist(int *complex) if ((f = par_sublist2(&c)) != -1) { int e = ecused; - *complex |= c; + *cmplx |= c; if (tok == DBAR || tok == DAMPER) { enum lextok qtok = tok; int sl; @@ -676,7 +676,7 @@ par_sublist(int *complex) zshlex(); while (tok == SEPER) zshlex(); - sl = par_sublist(complex); + sl = par_sublist(cmplx); set_sublist_code(p, (sl ? (qtok == DBAR ? WC_SUBLIST_OR : WC_SUBLIST_AND) : WC_SUBLIST_END), @@ -697,20 +697,20 @@ par_sublist(int *complex) /**/ static int -par_sublist2(int *complex) +par_sublist2(int *cmplx) { int f = 0; if (tok == COPROC) { - *complex = 1; + *cmplx = 1; f |= WC_SUBLIST_COPROC; zshlex(); } else if (tok == BANG) { - *complex = 1; + *cmplx = 1; f |= WC_SUBLIST_NOT; zshlex(); } - if (!par_pline(complex) && !f) + if (!par_pline(cmplx) && !f) return -1; return f; @@ -722,19 +722,19 @@ par_sublist2(int *complex) /**/ static int -par_pline(int *complex) +par_pline(int *cmplx) { int p; zlong line = toklineno; p = ecadd(0); - if (!par_cmd(complex, 0)) { + if (!par_cmd(cmplx, 0)) { ecused--; return 0; } if (tok == BAR) { - *complex = 1; + *cmplx = 1; cmdpush(CS_PIPE); zshlex(); while (tok == SEPER) @@ -742,7 +742,7 @@ par_pline(int *complex) ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0)); ecispace(p + 1, 1); ecbuf[p + 1] = ecused - 1 - p; - if (!par_pline(complex)) { + if (!par_pline(cmplx)) { tok = LEXERR; } cmdpop(); @@ -758,7 +758,7 @@ par_pline(int *complex) ecbuf[r + 1] = 2; ecbuf[r + 2] = ecstrcode("1"); - *complex = 1; + *cmplx = 1; cmdpush(CS_ERRPIPE); zshlex(); while (tok == SEPER) @@ -766,7 +766,7 @@ par_pline(int *complex) ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0)); ecispace(p + 1, 1); ecbuf[p + 1] = ecused - 1 - p; - if (!par_pline(complex)) { + if (!par_pline(cmplx)) { tok = LEXERR; } cmdpop(); @@ -786,14 +786,14 @@ par_pline(int *complex) /**/ static int -par_cmd(int *complex, int zsh_construct) +par_cmd(int *cmplx, int zsh_construct) { int r, nr = 0; r = ecused; if (IS_REDIROP(tok)) { - *complex = 1; + *cmplx = 1; while (IS_REDIROP(tok)) { nr += par_redir(&r, NULL); } @@ -801,57 +801,57 @@ par_cmd(int *complex, int zsh_construct) switch (tok) { case FOR: cmdpush(CS_FOR); - par_for(complex); + par_for(cmplx); cmdpop(); break; case FOREACH: cmdpush(CS_FOREACH); - par_for(complex); + par_for(cmplx); cmdpop(); break; case SELECT: - *complex = 1; + *cmplx = 1; cmdpush(CS_SELECT); - par_for(complex); + par_for(cmplx); cmdpop(); break; case CASE: cmdpush(CS_CASE); - par_case(complex); + par_case(cmplx); cmdpop(); break; case IF: - par_if(complex); + par_if(cmplx); break; case WHILE: cmdpush(CS_WHILE); - par_while(complex); + par_while(cmplx); cmdpop(); break; case UNTIL: cmdpush(CS_UNTIL); - par_while(complex); + par_while(cmplx); cmdpop(); break; case REPEAT: cmdpush(CS_REPEAT); - par_repeat(complex); + par_repeat(cmplx); cmdpop(); break; case INPAR: - *complex = 1; + *cmplx = 1; cmdpush(CS_SUBSH); - par_subsh(complex, zsh_construct); + par_subsh(cmplx, zsh_construct); cmdpop(); break; case INBRACE: cmdpush(CS_CURSH); - par_subsh(complex, zsh_construct); + par_subsh(cmplx, zsh_construct); cmdpop(); break; case FUNC: cmdpush(CS_FUNCDEF); - par_funcdef(complex); + par_funcdef(cmplx); cmdpop(); break; case DINBRACK: @@ -869,7 +869,7 @@ par_cmd(int *complex, int zsh_construct) static int inpartime = 0; if (!inpartime) { - *complex = 1; + *cmplx = 1; inpartime = 1; par_time(); inpartime = 0; @@ -882,13 +882,13 @@ par_cmd(int *complex, int zsh_construct) { int sr; - if (!(sr = par_simple(complex, nr))) { + if (!(sr = par_simple(cmplx, nr))) { if (!nr) return 0; } else { /* Take account of redirections */ if (sr > 1) { - *complex = 1; + *cmplx = 1; r += sr - 1; } } @@ -896,7 +896,7 @@ par_cmd(int *complex, int zsh_construct) break; } if (IS_REDIROP(tok)) { - *complex = 1; + *cmplx = 1; while (IS_REDIROP(tok)) (void)par_redir(&r, NULL); } @@ -914,7 +914,7 @@ par_cmd(int *complex, int zsh_construct) /**/ static void -par_for(int *complex) +par_for(int *cmplx) { int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT); int type; @@ -999,20 +999,20 @@ par_for(int *complex) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (csh || isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); incmdpos = 0; @@ -1020,7 +1020,7 @@ par_for(int *complex) } else if (unset(SHORTLOOPS)) { YYERRORV(oecused); } else - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[p] = (sel ? WCB_SELECT(type, ecused - 1 - p) : @@ -1036,7 +1036,7 @@ par_for(int *complex) /**/ static void -par_case(int *complex) +par_case(int *cmplx) { int oecused = ecused, brflag, p, pp, n = 1, type; int ona, onc; @@ -1153,7 +1153,7 @@ par_case(int *complex) pp = ecadd(0); ecstr(str); ecadd(ecnpats++); - par_save_list(complex); + par_save_list(cmplx); n++; if (tok == SEMIAMP) type = WC_CASE_AND; @@ -1183,7 +1183,7 @@ par_case(int *complex) /**/ static void -par_if(int *complex) +par_if(int *cmplx) { int oecused = ecused, p, pp, type, usebrace = 0; enum lextok xtok; @@ -1210,7 +1210,7 @@ par_if(int *complex) } pp = ecadd(0); type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF); - par_save_list(complex); + par_save_list(cmplx); incmdpos = 1; if (tok == ENDINPUT) { cmdpop(); @@ -1225,7 +1225,7 @@ par_if(int *complex) cmdpop(); cmdpush(nc); zshlex(); - par_save_list(complex); + par_save_list(cmplx); ecbuf[pp] = WCB_IF(type, ecused - 1 - pp); incmdpos = 1; cmdpop(); @@ -1234,7 +1234,7 @@ par_if(int *complex) cmdpop(); cmdpush(nc); zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) { cmdpop(); YYERRORV(oecused); @@ -1252,7 +1252,7 @@ par_if(int *complex) } else { cmdpop(); cmdpush(nc); - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[pp] = WCB_IF(type, ecused - 1 - pp); incmdpos = 1; break; @@ -1266,13 +1266,13 @@ par_if(int *complex) zshlex(); if (tok == INBRACE && usebrace) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) { cmdpop(); YYERRORV(oecused); } } else { - par_save_list(complex); + par_save_list(cmplx); if (tok != FI) { cmdpop(); YYERRORV(oecused); @@ -1293,33 +1293,33 @@ par_if(int *complex) /**/ static void -par_while(int *complex) +par_while(int *cmplx) { int oecused = ecused, p; int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE); p = ecadd(0); zshlex(); - par_save_list(complex); + par_save_list(cmplx); incmdpos = 1; while (tok == SEPER) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); zshlex(); @@ -1335,7 +1335,7 @@ par_while(int *complex) /**/ static void -par_repeat(int *complex) +par_repeat(int *cmplx) { int oecused = ecused, p; @@ -1352,27 +1352,27 @@ par_repeat(int *complex) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); zshlex(); } else if (unset(SHORTLOOPS)) { YYERRORV(oecused); } else - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[p] = WCB_REPEAT(ecused - 1 - p); } @@ -1388,7 +1388,7 @@ par_repeat(int *complex) /**/ static void -par_subsh(int *complex, int zsh_construct) +par_subsh(int *cmplx, int zsh_construct) { enum lextok otok = tok; int oecused = ecused, p, pp; @@ -1397,7 +1397,7 @@ par_subsh(int *complex, int zsh_construct) /* Extra word only needed for always block */ pp = ecadd(0); zshlex(); - par_list(complex); + par_list(cmplx); ecadd(WCB_END()); if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE)) YYERRORV(oecused); @@ -1418,7 +1418,7 @@ par_subsh(int *complex, int zsh_construct) cmdpush(CS_ALWAYS); zshlex(); - par_save_list(complex); + par_save_list(cmplx); while (tok == SEPER) zshlex(); @@ -1441,7 +1441,7 @@ par_subsh(int *complex, int zsh_construct) /**/ static void -par_funcdef(int *complex) +par_funcdef(int *cmplx) { int oecused = ecused, num = 0, onp, p, c = 0; int so, oecssub = ecssub; @@ -1523,7 +1523,7 @@ par_funcdef(int *complex) num++; zshlex(); } - *complex = (num > 0); + *cmplx = (num > 0); ecbuf[parg] = ecused - parg; /*?*/ ecbuf[parg+1] = num; } @@ -1585,15 +1585,15 @@ par_dinbrack(void) /**/ static int -par_simple(int *complex, int nr) +par_simple(int *cmplx, int nr) { int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0; - int c = *complex, nrediradd, assignments = 0; + int c = *cmplx, nrediradd, assignments = 0; r = ecused; for (;;) { if (tok == NOCORRECT) { - *complex = c = 1; + *cmplx = c = 1; nocorrect = 1; } else if (tok == ENVSTRING) { char *p, *name, *str; @@ -1621,7 +1621,7 @@ par_simple(int *complex, int nr) */ if (p[1] == Inpar && (*p == Equals || *p == Inang || *p == OutangProc)) { - *complex = 1; + *cmplx = 1; break; } } @@ -1633,10 +1633,10 @@ par_simple(int *complex, int nr) int oldcmdpos = incmdpos, n, type2; /* - * We consider array setting complex because it can + * We consider array setting cmplx because it can * contain process substitutions, which need a valid job. */ - *complex = c = 1; + *cmplx = c = 1; p = ecadd(0); incmdpos = 0; if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') { @@ -1668,7 +1668,7 @@ par_simple(int *complex, int nr) if (tok == STRING) { int redir_var = 0; - *complex = 1; + *cmplx = 1; incmdpos = 0; if (!isset(IGNOREBRACES) && *tokstr == Inbrace) @@ -1687,7 +1687,7 @@ par_simple(int *complex, int nr) if (IS_REDIROP(tok) && tokfd == -1) { - *complex = c = 1; + *cmplx = c = 1; nrediradd = par_redir(&r, idstring); p += nrediradd; sr += nrediradd; @@ -1708,7 +1708,7 @@ par_simple(int *complex, int nr) zshlex(); } } else if (IS_REDIROP(tok)) { - *complex = c = 1; + *cmplx = c = 1; nrediradd = par_redir(&r, NULL); p += nrediradd; sr += nrediradd; @@ -1723,7 +1723,7 @@ par_simple(int *complex, int nr) if (assignments) YYERROR(oecused); - *complex = c; + *cmplx = c; lineno = 0; incmdpos = 1; cmdpush(CS_FUNCDEF); @@ -1773,7 +1773,7 @@ par_simple(int *complex, int nr) if (argc == 0) { /* * Anonymous function, possibly with arguments. - * N.B. for complex structures in particular + * N.B. for cmplx structures in particular * ( ... ) we rely on lower level code doing this * to get the immediately following word (the * first token after the ")" has already been @@ -1807,7 +1807,8 @@ par_simple(int *complex, int nr) argc++; zshlex(); } - *complex = (argc > 0); + if (argc > 0) + *cmplx = 1; ecbuf[parg] = ecused - parg; /*?*/ ecbuf[parg+1] = argc; } diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 193757090..10491a229 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -279,6 +279,10 @@ >anon func >lsfoo + print foo | () cat +0:Simple anonymous function should not simplify enclosing pipeline +>foo + %clean rm -f file.in file.out -- cgit 1.4.1