From 41ef7f76cf898fdcdb8994bb2993e659b7f95fd2 Mon Sep 17 00:00:00 2001 From: Harald van Dijk Date: Sun, 3 Jan 2021 23:54:36 +0000 Subject: [PATCH] Invocation: fix infinite loop on 'ksh +s' When starting ksh +s, it gets stuck in an infinite loop continually trying to parse its own binary as a shell script and rejecting it: $ arch/linux.i386-64/bin/ksh +s arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] [...] $ echo 'echo "this is stdin"' | arch/linux.i386-64/bin/ksh +s arch/linux.i386-64/bin/ksh: arch/linux.i386-64/bin/ksh: cannot execute [Exec format error] (no loop, but still ksh trying to parse itself) src/cmd/ksh93/sh/init.c: sh_init(): - When forcing on the '-s' option upon finding no command arguments, also update sh.offoptions, a.k.a. shp->offoptions. This avoids the inconsistent state causing this problem. In main.c, there is: if(sh_isoption(SH_SFLAG)) fdin = 0; else (code to open $0 as a file) This was entering the else block because sh_isoption(SH_SFLAG) was returning 0, and $0 is set to the ksh binary as it is supposed to when no other script is provided. When I looked for why sh_isoption was returning 0, I found main.c's for(i=0; ioffoptions.v); i++) shp->options.v[i] &= ~shp->offoptions.v[i]; Before this loop, shp->offoptions tracks which options were explicitly disabled by the user on the command line. The effect of this loop is to make "explicitly disabled" take precedence over "implicitly enabled". My patch removes the registration of the +s option. Fixes: https://github.com/ksh93/ksh/issues/150 Co-authored-by: Martijn Dekker --- NEWS | 8 ++++++++ src/cmd/ksh93/data/builtins.c | 2 +- src/cmd/ksh93/include/defs.h | 2 +- src/cmd/ksh93/include/version.h | 2 +- src/cmd/ksh93/sh/init.c | 3 +++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index ff7a757dd..e7c70848c 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,14 @@ For full details, see the git log at: https://github.com/ksh93/ksh Any uppercase BUG_* names are modernish shell bug IDs. +2021-01-03: + +- The invocation + $ ksh +s + caused an infinite loop and corrupted ~/.sh_history. This is now fixed so + that the '-s' option is automatically turned on if there are no non-option + command arguments, as documented in Bolsky & Korn (1995), p. 261. + 2020-10-22: - Fixed: 'typeset -F0', 'typeset -E0', and 'typeset -X0' floating point diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c index 262ff4371..54b0f3181 100644 --- a/src/cmd/ksh93/data/builtins.c +++ b/src/cmd/ksh93/data/builtins.c @@ -1522,7 +1522,7 @@ USAGE_LICENSE "[+-?Executing \bcommand -p\b \a...\a .]" "}" "[s?Read the commands from standard input. The positional parameters will be " - "initialized from \aarg\a.]" + "initialized from \aarg\a. This option is forced on if no \aarg\a is given.]" "[D\f:dump-strings\f?Do not execute the script, but output the set of double " "quoted strings preceded by a \b$\b. These strings are needed for " "localization of the script to different locales.]" diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h index f0850f4e4..459ac1241 100644 --- a/src/cmd/ksh93/include/defs.h +++ b/src/cmd/ksh93/include/defs.h @@ -264,7 +264,7 @@ struct shared Dt_t *transdict; \ char ifstable[256]; \ unsigned long test; \ - Shopt_t offoptions; \ + Shopt_t offoptions; /* options that were explicitly disabled by the user on the command line */ \ Shopt_t glob_options; \ Namval_t *typeinit; \ Namfun_t nvfun; \ diff --git a/src/cmd/ksh93/include/version.h b/src/cmd/ksh93/include/version.h index cfef2eae7..4e8840c20 100644 --- a/src/cmd/ksh93/include/version.h +++ b/src/cmd/ksh93/include/version.h @@ -17,4 +17,4 @@ * David Korn * * * ***********************************************************************/ -#define SH_RELEASE "93u+m 2020-10-22" +#define SH_RELEASE "93u+m 2021-01-03" diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c index f643c978e..c37425127 100644 --- a/src/cmd/ksh93/sh/init.c +++ b/src/cmd/ksh93/sh/init.c @@ -1355,7 +1355,10 @@ Shell_t *sh_init(register int argc,register char *argv[], Shinit_f userinit) shp->st.dolv=argv+(argc-1)-shp->st.dolc; shp->st.dolv[0] = argv[0]; if(shp->st.dolc < 1) + { sh_onoption(SH_SFLAG); + off_option(&shp->offoptions,SH_SFLAG); + } if(!sh_isoption(SH_SFLAG)) { shp->st.dolc--;