Skip to content

Commit

Permalink
Merge branch 'dev' into fix-heredoc-interactive-crash
Browse files Browse the repository at this point in the history
  • Loading branch information
McDutchie committed Feb 23, 2024
2 parents 5217bde + 15ef3d1 commit c5f2972
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 39 deletions.
7 changes: 7 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library.
- Fixed a crash that occurred when starting ksh with no TERM variable in the
environment (e.g., in single user mode on NetBSD and DragonFlyBSD).

- Fixed a regression of 'return' within traps, reintroduced on 2023-12-25
after being fixed on 2020-09-09. The regression caused a 'return' or
'exit' with no arguments to assume the before-trap exit status instead of
that of the last-run command. This broke the shipped 'autocd' function.

- Fixed some integer overflows that could occur when using TMOUT.

- Fixed a crash on Solaris and illumos when cancelling a here-document
with ^C or ^D in an interactive shell.

Expand Down
7 changes: 5 additions & 2 deletions src/cmd/ksh93/bltins/cflow.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ int b_return(int n, char *argv[],Shbltin_t *context)
int r;
intmax_t l = strtoll(*argv, NULL, 10);
if(do_exit)
{
n = (int)(l & SH_EXITMASK); /* exit: apply bitmask before conversion to avoid undefined int overflow */
if (sh.intrap)
sh.intrap_exit_n = 1;
}
else if(r = (int)l, l != (intmax_t)r) /* return: convert to int and check for overflow (should be safe enough) */
{
errormsg(SH_DICT,ERROR_warn(0),"%s: out of range",*argv);
Expand All @@ -79,8 +83,7 @@ int b_return(int n, char *argv[],Shbltin_t *context)
}
else
{
/* no argument: pass down $? (but in a trap action, pass down the pre-trap $?) */
n = sh.intrap ? sh.oldexit : sh.savexit;
n = sh.savexit; /* no argument: pass down $? */
if(do_exit)
n &= SH_EXITMASK;
}
Expand Down
18 changes: 9 additions & 9 deletions src/cmd/ksh93/bltins/read.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@

struct read_save
{
char **argv;
char *prompt;
int fd;
int plen;
int flags;
ssize_t len;
long timeout;
char **argv;
char *prompt;
int fd;
int plen;
int flags;
ssize_t len;
Sflong_t timeout;
};

int b_read(int argc,char *argv[], Shbltin_t *context)
Expand All @@ -66,7 +66,7 @@ int b_read(int argc,char *argv[], Shbltin_t *context)
const char *msg = e_file+4;
int r, flags=0, fd=0;
ssize_t len=0;
long timeout = 1000*sh.st.tmout;
Sflong_t timeout = 1000*(Sflong_t)sh.st.tmout;
int save_prompt, fixargs=context->invariant;
struct read_save *rp;
static char default_prompt[3] = {ESC,ESC};
Expand Down Expand Up @@ -212,7 +212,7 @@ static void timedout(void *handle)
* <flags> is union of -A, -r, -s, and contains delimiter if not '\n'
* <timeout> is the number of milliseconds until timeout
*/
int sh_readline(char **names, volatile int fd, int flags, ssize_t size, long timeout)
int sh_readline(char **names, volatile int fd, int flags, ssize_t size, Sflong_t timeout)
{
ssize_t c;
unsigned char *cp;
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ extern int sh_outtype(Sfio_t*);
extern char *sh_mactry(char*);
extern int sh_mathstd(const char*);
extern void sh_printopts(Shopt_t,int,Shopt_t*);
extern int sh_readline(char**,volatile int,int,ssize_t,long);
extern int sh_readline(char**,volatile int,int,ssize_t,Sflong_t);
extern Sfio_t *sh_sfeval(char*[]);
extern void sh_setmatch(const char*,int,int,int[],int);
extern void sh_scope(struct argnod*, int);
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/ksh93/include/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ struct Shell_s
char *comdiv; /* points to sh -c argument */
char *prefix; /* prefix for compound assignment */
sigjmp_buf *jmplist; /* longjmp return stack */
int oldexit; /* saves pre-trap exit status for 'exit' default in trap actions */
pid_t bckpid; /* background process id */
pid_t cpid;
pid_t spid; /* subshell process id */
Expand All @@ -312,6 +311,7 @@ struct Shell_s
int savesig;
unsigned char *sigflag; /* pointer to signal states */
char intrap; /* set while executing a trap action */
char intrap_exit_n; /* set if 'exit n' within trap */
uint32_t srand_upper_bound;
char forked;
char binscript;
Expand Down
11 changes: 4 additions & 7 deletions src/cmd/ksh93/sh/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,11 +528,7 @@ int sh_trap(const char *trap, int mode)
if(jmpval==SH_JMPSCRIPT)
indone=0;
else
{
if(jmpval==SH_JMPEXIT)
savxit = sh.exitval;
jmpval=SH_JMPTRAP;
}
}
sh_popcontext(&buff);
/* re-allow last-command exec optimisation unless the command we executed set a trap */
Expand All @@ -541,8 +537,10 @@ int sh_trap(const char *trap, int mode)
sh.intrap--;
sfsync(sh.outpool);
savxit_return = sh.exitval;
if(jmpval!=SH_JMPEXIT && jmpval!=SH_JMPFUN)
sh.exitval=savxit;
if(sh.intrap_exit_n)
sh.intrap_exit_n = 0;
else
sh.exitval = savxit;
stkset(sh.stk,savptr,staktop);
fcrestore(&savefc);
if(was_history)
Expand Down Expand Up @@ -666,7 +664,6 @@ noreturn void sh_done(int sig)
if(t=sh.st.trapcom[0])
{
sh.st.trapcom[0]=0; /* should free but not long */
sh.oldexit = savxit;
sh_trap(t,0);
savxit = sh.exitval;
}
Expand Down
1 change: 0 additions & 1 deletion src/cmd/ksh93/sh/subshell.c
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,6 @@ Sfio_t *sh_subshell(Shnode_t *t, volatile int flags, int comsub)
/* trap on EXIT not handled by child */
char *trap=sh.st.trapcom[0];
sh.st.trapcom[0] = 0; /* prevent recursion */
sh.oldexit = sh.exitval;
sh_trap(trap,0);
free(trap);
}
Expand Down
4 changes: 1 addition & 3 deletions src/cmd/ksh93/sh/xec.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,8 +896,6 @@ int sh_exec(const Shnode_t *t, int flags)
sh_offstate(SH_DEFPATH);
if(!(flags & sh_state(SH_ERREXIT)))
sh_offstate(SH_ERREXIT);
if(!sh.intrap)
sh.oldexit = sh.exitval;
sh.exitval=0;
sh.lastsig = 0;
sh.chldexitsig = 0;
Expand Down Expand Up @@ -1993,7 +1991,7 @@ int sh_exec(const Shnode_t *t, int flags)
save_prompt = sh.nextprompt;
sh.nextprompt = 3;
sh.timeout = 0;
sh.exitval=sh_readline(&null_pointer,0,1,0,1000*sh.st.tmout);
sh.exitval=sh_readline(&null_pointer,0,1,0,1000*(Sflong_t)sh.st.tmout);
sh.nextprompt = save_prompt;
if(sh.exitval||sfeof(sfstdin)||sferror(sfstdin))
{
Expand Down
15 changes: 0 additions & 15 deletions src/cmd/ksh93/tests/pty.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1322,21 +1322,6 @@ c \Ek
r ^:prompt: "\$SHELL" -o vi -c 'read -s "foo\?:prompt: "'$
!

((multiline && (SHOPT_VSH || SHOPT_ESH))) && TERM=vt100 tst $LINENO <<"!"
L crash when TERM is undefined
# https://github.com/ksh93/ksh/issues/722
d 40
p :test-1:
w unset TERM
p :test-2:
w "$SHELL"
p :test-3:
w print Exit status $?
r print
r ^Exit status 0\r\n$
!

tst $LINENO <<"!"
L crash when attempting to cancel a heredoc in an interactive shell
# https://github.com/ksh93/ksh/pull/721
Expand Down
10 changes: 10 additions & 0 deletions src/cmd/ksh93/tests/return.sh
Original file line number Diff line number Diff line change
Expand Up @@ -269,5 +269,15 @@ then max=$(getconf INT_MAX) min=$(getconf INT_MIN) err=$tmp/stderr
"(expected status 128 and '', got status $e and $(printf %q "$(<$err)"))"
fi

# ======
# old AT&T bug reintroduced in v1.0.8 (commit aea99158)
f() { true; return; }
trap 'f; echo $? >out' USR1
(exit 13)
kill -s USR1 ${.sh.pid}
trap - USR1
unset -f f
[[ $(<out) == 0 ]] || err_exit "default return status in traps is broken (expected 0, got $(<out))"

# ======
exit $((Errors<125?Errors:125))

0 comments on commit c5f2972

Please sign in to comment.