diff --git a/NEWS b/NEWS index b90627569873..c3f218a76696 100644 --- a/NEWS +++ b/NEWS @@ -4,6 +4,9 @@ Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. 2024-08-26: +- Fixed an infinite loop that occurred when a syntax error was thrown + for an arithmetic 'for' loop on the interactive command line. + - [v1.1] Backported a change to '_' in types from the unreleased ksh 93v- beta. If a 'typeset -T' type declaration sets a discipline function for one of its subvariables (such as var.get() or var.getn()), then, within diff --git a/src/cmd/ksh93/include/shlex.h b/src/cmd/ksh93/include/shlex.h index 2a46d0de1f9f..3aa1d403bb44 100644 --- a/src/cmd/ksh93/include/shlex.h +++ b/src/cmd/ksh93/include/shlex.h @@ -52,7 +52,7 @@ struct _shlex_pvt_lexdata_ char docword; char nested_tilde; char *docend; - char noarg; + char inlexskip; /* set when sh_lex() is called from sh_lexskip() */ char warn; char message; char arith; diff --git a/src/cmd/ksh93/sh/lex.c b/src/cmd/ksh93/sh/lex.c index ed8ed2db606e..d72f7feb98a4 100644 --- a/src/cmd/ksh93/sh/lex.c +++ b/src/cmd/ksh93/sh/lex.c @@ -150,13 +150,13 @@ static void lex_advance(Sfio_t *iop, const char *buff, int size, void *context) { size -= (lp->lexd.first-(char*)buff); buff = lp->lexd.first; - if(!lp->lexd.noarg) + if(!lp->lexd.inlexskip) lp->arg = stkseek(sh.stk,ARGVAL); #if SHOPT_KIA lp->lexd.kiaoff += ARGVAL; #endif /* SHOPT_KIA */ } - if(size>0 && (lp->arg||lp->lexd.noarg)) + if(size>0 && (lp->arg||lp->lexd.inlexskip)) { sfwrite(sh.stk,buff,size); lp->lexd.first = 0; @@ -344,7 +344,7 @@ int sh_lex(Lex_t* lp) /* end-of-file */ if(mode==ST_BEGIN) return lp->token=EOFSYM; - if(mode >ST_NORM && lp->lexd.level>0) + if(mode >ST_NORM && lp->lexd.level>0 && !lp->lexd.inlexskip) { switch(c=endchar(lp)) { @@ -706,7 +706,7 @@ int sh_lex(Lex_t* lp) mode = ST_NORM; continue; case S_LIT: - if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */ + if(oldmode(lp)==ST_NONE && !lp->lexd.inlexskip) /* in ((...)) */ { if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']') { @@ -1741,13 +1741,13 @@ void sh_lexskip(Lex_t *lp,int close, int copy, int state) char *cp; lp->lexd.nest = close; lp->lexd.lex_state = state; - lp->lexd.noarg = 1; + lp->lexd.inlexskip = 1; if(copy) fcnotify(lex_advance,lp); else lp->lexd.nocopy++; sh_lex(lp); - lp->lexd.noarg = 0; + lp->lexd.inlexskip = 0; if(copy) { fcnotify(0,lp); diff --git a/src/cmd/ksh93/tests/loop.sh b/src/cmd/ksh93/tests/loop.sh index 8c4b2e94c42f..a3db88da2f0a 100755 --- a/src/cmd/ksh93/tests/loop.sh +++ b/src/cmd/ksh93/tests/loop.sh @@ -69,5 +69,17 @@ got=$(for i in a b c; do print -n $i; for j in 1 2 3; do print -n $j; for k in x exp=a1xb1xc1x [[ $got == "$exp" ]] || err_exit "'continue 3' broken (expected '$exp', got '$got')" +# ====== +# arithmetic for + +got=$(eval 'for((i=0,i<10,i++)); do :; done' 2>&1) +exp=': syntax error at line 1: `))'\'' unexpected' +[[ $got == *"$exp" ]] || err_exit "arithmetic for syntax error" \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" +got=$(eval 'for(())' 2>&1) +exp=': syntax error at line 1: `))'\'' unexpected' +[[ $got == *"$exp" ]] || err_exit "arithmetic for syntax error" \ + "(expected match of *$(printf %q "$exp"), got $(printf %q "$got"))" + # ====== exit $((Errors<125?Errors:125))