From ed76f95739af041537b6a0680a74e701675b5ea5 Mon Sep 17 00:00:00 2001 From: wenyuzifang Date: Wed, 17 Sep 2025 18:30:13 +0800 Subject: [PATCH] Update code from upstream --- ksh-1.0.11-SHLVL.patch | 139 +++++++++++ ksh-1.0.11-redir.patch | 117 ++++++++++ ksh-1.0.11-segfault-sigwinch.patch | 266 ++++++++++++++++++++++ ksh-1.0.11-ssh-multibyte-long-paste.patch | 94 ++++++++ ksh-1.0.11-stty-noecho.patch | 77 +++++++ ksh.spec | 28 ++- 6 files changed, 715 insertions(+), 6 deletions(-) create mode 100644 ksh-1.0.11-SHLVL.patch create mode 100644 ksh-1.0.11-redir.patch create mode 100644 ksh-1.0.11-segfault-sigwinch.patch create mode 100644 ksh-1.0.11-ssh-multibyte-long-paste.patch create mode 100644 ksh-1.0.11-stty-noecho.patch diff --git a/ksh-1.0.11-SHLVL.patch b/ksh-1.0.11-SHLVL.patch new file mode 100644 index 0000000..b08c582 --- /dev/null +++ b/ksh-1.0.11-SHLVL.patch @@ -0,0 +1,139 @@ +From 7c945bdd6ba44bbb490504f44904ac65d705dd17 Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Sun, 27 Oct 2024 01:34:38 +0000 +Subject: [PATCH] Fix crash on 'exec' after 'unset SHLVL' (re: fa0f9796) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Vincent Mihalkovič (@vmihalko) reports: +> If the user unsets the SHLVL variable and later replaces the +> shell by executing a command, ksh will segfault. +> +> Reproducer +> +> # unset -v SHLVL +> # exec bash +> Segmaentation fault (core dumped) +> +> Reason +> +> The reason for this is that the SHLVL variable is getting +> decremented without any guard making sure it's still in the +> environment, see: +> +> src/cmd/ksh93/bltins/misc.c: +> 145: /* if the main shell is about to be replaced, decrease SHLVL +> to cancel out a subsequent increase */ +> 146: if(!sh.realsubshell) +> 147: (*SHLVL->nvalue.ip)--; + +This should be fixed so that SHLVL can be unset safely and lose its +special properties like other special variables do. + +src/cmd/ksh93/sh/init.c, +src/cmd/ksh93/include/shell.h: +- Move the static 'shlvl' in init.c to the sh state struct, so that + 'sh.shlvl' can be accessed from the entire ksh93 code base. +- Change its type from int to int32_t -- this is more correct as + nv_getval() uses this type to retrieve the value. In practice, + this makes no difference because sizeof(int) == sizeof(int32_t), + but this is not guaranteed by the standards. + +src/cmd/ksh93/bltins/misc.c: +- Access sh.shlvl directly instead of dereferencing the SHLVL value + pointer, as this pointer is invalidated upon 'unset SHLVL'. This + fixes the bug. + +Resolves: https://github.com/ksh93/ksh/issues/788 +--- + src/cmd/ksh93/bltins/misc.c | 2 +- + src/cmd/ksh93/include/shell.h | 1 + + src/cmd/ksh93/sh/init.c | 7 +++---- + src/cmd/ksh93/tests/variables.sh | 7 +++++++ + 4 files changed, 12 insertions(+), 5 deletions(-) + +diff --git a/src/cmd/ksh93/bltins/misc.c b/src/cmd/ksh93/bltins/misc.c +index cb7e883..1d49162 100644 +--- a/src/cmd/ksh93/bltins/misc.c ++++ b/src/cmd/ksh93/bltins/misc.c +@@ -144,7 +144,7 @@ int b_exec(int argc,char *argv[], Shbltin_t *context) + return 1; + /* if the main shell is about to be replaced, decrease SHLVL to cancel out a subsequent increase */ + if(!sh.realsubshell) +- (*SHLVL->nvalue.ip)--; ++ sh.shlvl--; + sh_onstate(SH_EXEC); + if(sh.subshell && !sh.subshare) + { +diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h +index c28b159..96d982a 100644 +--- a/src/cmd/ksh93/include/shell.h ++++ b/src/cmd/ksh93/include/shell.h +@@ -270,6 +270,7 @@ struct Shell_s + * Programs using libshell should not rely on them as they may change. */ + int subshell; /* set for virtual subshell */ + int realsubshell; /* ${.sh.subshell}, actual subshell level (including virtual and forked) */ ++ int32_t shlvl; /* $SHLVL, non-subshell child shell level */ + char shcomp; /* set when running shcomp */ + unsigned char trapnote; /* set when trap/signal is pending */ + struct sh_scoped st; /* scoped information */ +diff --git a/src/cmd/ksh93/sh/init.c b/src/cmd/ksh93/sh/init.c +index 1242789..1f1b71e 100644 +--- a/src/cmd/ksh93/sh/init.c ++++ b/src/cmd/ksh93/sh/init.c +@@ -220,7 +220,6 @@ static Init_t *nv_init(void); + #if SHOPT_STATS + static void stat_init(void); + #endif +-static int shlvl; + static int rand_shift; + + /* +@@ -1352,7 +1351,7 @@ Shell_t *sh_init(int argc,char *argv[], Shinit_f userinit) + nv_putval(ENVNOD,sfstruse(sh.strbuf),NV_RDONLY); + } + /* increase SHLVL */ +- shlvl++; ++ sh.shlvl++; + #if SHOPT_SPAWN + { + /* +@@ -1672,7 +1671,7 @@ void sh_reinit(void) + else + env_import_attributes(env_init()); + /* Increase SHLVL */ +- shlvl++; ++ sh.shlvl++; + /* call user init function, if any */ + if(sh.userinit) + (*sh.userinit)(&sh, 1); +@@ -1804,7 +1803,7 @@ static Init_t *nv_init(void) + sh.nvfun.last = (char*)&sh; + sh.nvfun.nofree = 1; + sh.var_base = sh.var_tree = sh_inittree(shtab_variables); +- SHLVL->nvalue.ip = &shlvl; ++ SHLVL->nvalue.lp = &sh.shlvl; + ip->IFS_init.hdr.disc = &IFS_disc; + ip->PATH_init.disc = &RESTRICTED_disc; + ip->PATH_init.nofree = 1; +diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh +index 12a797a..5754085 100755 +--- a/src/cmd/ksh93/tests/variables.sh ++++ b/src/cmd/ksh93/tests/variables.sh +@@ -1619,5 +1619,12 @@ got=$(set +x; { "$SHELL" -c ' + "(expected status 0, $(printf %q "$exp");" \ + "got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" + ++# ====== ++# exec after unset SHLVL ++# https://github.com/ksh93/ksh/issues/788 ++{ "$SHELL" -c 'unset SHLVL; exec true'; } 2>/dev/null ++(((e=$?)==0)) || err_exit "crash after unsetting SHLVL" \ ++ "(expected status 0, got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))" ++ + # ====== + exit $((Errors<125?Errors:125)) +-- +2.46.2 + diff --git a/ksh-1.0.11-redir.patch b/ksh-1.0.11-redir.patch new file mode 100644 index 0000000..786010f --- /dev/null +++ b/ksh-1.0.11-redir.patch @@ -0,0 +1,117 @@ +From 5def43983de3ecfa38c805c02a1f0d6f1581160c Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Thu, 31 Oct 2024 20:56:54 +0000 +Subject: [PATCH] Add forking workaround for block stdout redir (re: e373e8c1) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reproducer: + + ok=$({ true >&2; } >&2; echo OK); echo $ok + +This should output "OK" but currently outputs nothing. + +Looks like the sh_subfork() workaround must also be implemented for +the TSETIO case in sh_exec(), as that is where redirections for +blocks and compound commands are handled. This avoids inconsistent +behaviour that happens if sh_subfork() is called later for the +inside redirection. + +src/cmd/ksh93/sh/xec.c: sh_exec(): case TSETIO: +- Also fork if standard output redirections attached to blocks are + executed within a non-subshare command substitution. + +Thanks to Vincent Mihalkovič (@vmihalko) for the report. +Resolves: https://github.com/ksh93/ksh/issues/784 +--- + NEWS | 8 ++++++++ + src/cmd/ksh93/include/version.h | 2 +- + src/cmd/ksh93/sh/xec.c | 15 ++++++++------- + src/cmd/ksh93/tests/io.sh | 32 +++++++++++++++++++++++++++++++- + 4 files changed, 48 insertions(+), 9 deletions(-) + +diff --git a/src/cmd/ksh93/sh/xec.c b/src/cmd/ksh93/sh/xec.c +index d48b72dc390b..c90b13b1f6d5 100644 +--- a/src/cmd/ksh93/sh/xec.c ++++ b/src/cmd/ksh93/sh/xec.c +@@ -1712,21 +1712,22 @@ int sh_exec(const Shnode_t *t, int flags) + int jmpval, waitall = 0; + int simple = (t->fork.forktre->tre.tretyp&COMMSK)==TCOM; + struct checkpt *buffp = stkalloc(sh.stk,sizeof(struct checkpt)); +- if(sh.subshell && !sh.subshare && t->fork.forkio) ++ if(sh.subshell && !sh.subshare) + { +- /* Subshell forking workaround for https://github.com/ksh93/ksh/issues/161 +- * Check each redirection for >&- or <&- ++ /* Subshell forking workaround for: ++ * https://github.com/ksh93/ksh/issues/161 (check each redirection for >&- or <&-) ++ * https://github.com/ksh93/ksh/issues/784 (check for stdout in a command substitution) + * TODO: find the elusive real fix */ +- struct ionod *i = t->fork.forkio; +- do ++ struct ionod *i; ++ for (i = t->fork.forkio; i; i = i->ionxt) + { +- if((i->iofile & ~(IOUFD|IOPUT)) == (IOMOV|IORAW) && !strcmp(i->ioname,"-")) ++ unsigned f = i->iofile; ++ if ((f & ~(IOUFD|IOPUT))==(IOMOV|IORAW) && !strcmp(i->ioname,"-") || (f & IOUFD)==1 && sh.comsub) + { + sh_subfork(); + break; + } + } +- while(i = i->ionxt); + } + sh_pushcontext(buffp,SH_JMPIO); + if(type&FPIN) +diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh +index 2b23a9d1d968..669c72529707 100755 +--- a/src/cmd/ksh93/tests/io.sh ++++ b/src/cmd/ksh93/tests/io.sh +@@ -936,7 +936,6 @@ fi # can_close_stdout + # ====== + # Command substitution hangs, writing infinite zero bytes, when redirecting standard output on a built-in that forks + # https://github.com/ksh93/ksh/issues/416 +-exp='line' + "$SHELL" -c 'echo "$(ulimit -t unlimited >/dev/null 2>&1; echo "ok $$")"' >out 2>&1 & + pid=$! + (sleep 1; kill -9 "$pid") 2>/dev/null & +@@ -947,6 +946,37 @@ then kill "$!" # the sleep process + else err_exit "comsub hangs after fork with stdout redirection" + fi + ++# https://github.com/ksh93/ksh/issues/416#issuecomment-1008866883 ++exp='line' ++"$SHELL" -c 'alias foo=bar; echo $(alias foo >/dev/null; echo "$1")' "$0" "$exp" >out 2>&1 & ++pid=$! ++(sleep 1; kill -9 "$pid") 2>/dev/null & ++if wait "$pid" 2>/dev/null ++then kill "$!" # the sleep process ++ [[ $(&2; } >&2 ++ echo A ++ } ++ Result=$(BugFunction) ++ echo $Result ++' >out 2>&1 & ++pid=$! ++(sleep 1; kill -9 "$pid") 2>/dev/null & ++if wait "$pid" 2>/dev/null ++then kill "$!" # the sleep process ++ [[ $( +Date: Fri, 28 Mar 2025 02:59:46 +0000 +Subject: [PATCH] Fix segfault upon SIGWINCH after 'stty -echo' (re: 83630f9d) + +After disabling terminal echo (stty -echo), ksh either crashes or +writes garbage to the terminal upon resizing the terminal window. +This also affects the use of ksh for 'M-x shell' in emacs. + +Analysis: The ed_viread and ed_emacsread functions declare buffers +as local (automatic) variables that are destroyed when the function +exits, but other functions then access then using globally declared +pointers in structs of type Edit_t, Emacs_t and Vi_t. + +However, upon 'stty -echo', the terminal cannot be set to raw mode, +so the tty_raw call fails in these two functions. At this point, +they fall back to ed_read and return, never initialising those +pointers. But the SIGWINCH handling routine in edit.c calls redraw +routines that depend on those pointers being valid -- and crash. + +src/cmd/ksh93/edit/emacs.c: ed_emacsread(): +- Attempt to set raw mode before doing or initialising anything + else: move the tty_raw call and ed_read fallback to the start. + This avoids superfluous init and makes more sense. +- Before returning, reset all global pointers that point to this + function call's local variables to NULL. (To aid with this, use a + 'done' goto label and an 'r' variable for the return code.) This + ensures these pointers will be either valid or NULL, making + debugging easier, as well as allowing the code to check for this. + +src/cmd/ksh93/edit/vi.c: ed_viread(): +- Same changes as for emacs. + +src/cmd/ksh93/edit/edit.c: ed_read(): +- If e_prompt is NULL, that is now an indication that ed_emacsread + or ed_viread are not being used because the tty_raw call failed; + therefore, skip SIGWINCH handling, except for flushing the notify + buffer (see 667034ff). This fixes the crash. + +Thanks to @nickpapadonis for the report. +Resolves: https://github.com/ksh93/ksh/issues/827 +--- + src/cmd/ksh93/edit/edit.c | 22 +++++++++++++++++---- + src/cmd/ksh93/edit/emacs.c | 27 ++++++++++++++----------- + src/cmd/ksh93/edit/vi.c | 40 ++++++++++++++++---------------------- + 3 files changed, 51 insertions(+), 38 deletions(-) + +diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c +index 0f46b8d..6ff1555 100644 +--- a/src/cmd/ksh93/edit/edit.c ++++ b/src/cmd/ksh93/edit/edit.c +@@ -617,6 +617,16 @@ static void ed_nputchar(Edit_t *ep, int n, int c) + } + #endif /* SHOPT_ESH || SHOPT_VSH */ + ++/* ++ * Show any buffered 'set -b' job notification(s) ++ */ ++static void flush_notifybuf(void) ++{ ++ char *cp; ++ if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp) ++ sfputr(sfstderr, cp, -1); ++} ++ + /* + * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set + * Use select(2) (via sfpkrd()) to wait for input if possible +@@ -656,7 +666,12 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + if(sh.winch && sh_editor_active() && sh_isstate(SH_INTERACTIVE)) + { + int n, newsize; +- char *cp; ++ if(!ep->e_prompt) ++ { ++ /* ed_emacsread or ed_viread was unable to put the tty in raw mode */ ++ flush_notifybuf(); ++ goto skipwinch; ++ } + sh_winsize(NULL,&newsize); + ed_putchar(ep,'\r'); + /* +@@ -678,9 +693,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + ed_putchar(ep,'\r'); + } + ed_flush(ep); +- /* show any buffered 'set -b' job notification(s) */ +- if(sh.notifybuf && (cp = sfstruse(sh.notifybuf)) && *cp) +- sfputr(sfstderr, cp, -1); ++ flush_notifybuf(); + /* update window size */ + ep->e_winsz = newsize-1; + if(ep->e_winsz < MINWINDOW) +@@ -704,6 +717,7 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) + emacs_redraw(ep->e_emacs); + #endif /* SHOPT_ESH && SHOPT_VSH */ + } ++ skipwinch: + #endif /* SHOPT_ESH || SHOPT_VSH */ + sh.winch = 0; + /* an interrupt that should be ignored */ +diff --git a/src/cmd/ksh93/edit/emacs.c b/src/cmd/ksh93/edit/emacs.c +index 37239a5..1a65c4d 100644 +--- a/src/cmd/ksh93/edit/emacs.c ++++ b/src/cmd/ksh93/edit/emacs.c +@@ -182,6 +182,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + Edit_t *ed = (Edit_t*)context; + int c; + int i; ++ int r = -1; /* return code */ + genchar *out; + int count; + Emacs_t *ep = ed->e_emacs; +@@ -191,6 +192,10 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + genchar *kptr; + char prompt[PRSIZE]; + genchar Screen[MAXLINE]; ++ /* Set raw mode */ ++ if(tty_raw(ERRIO,0) < 0) ++ return reedit ? reedit : ed_read(context, fd, buff, scend, 0); ++ /* Initialize some things */ + memset(Screen,0,sizeof(Screen)); + if(!ep) + { +@@ -203,10 +208,6 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + ep->screen = Screen; + ep->lastdraw = FINAL; + ep->ehist = 0; +- if(tty_raw(ERRIO,0) < 0) +- { +- return reedit ? reedit : ed_read(context,fd,buff,scend,0); +- } + raw = 1; + /* This mess in case the read system call fails */ + ed_setup(ep->ed,fd,reedit); +@@ -237,6 +238,7 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + } + ep->in_mult = hloff; /* save pos in last command */ + #endif /* ESH_NFIRST */ ++ /* Handle user interrupt, user quit, or EOF */ + i = sigsetjmp(env,0); + if (i !=0) + { +@@ -248,10 +250,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + } + tty_cooked(ERRIO); + if (i == UEOF) +- { +- return 0; /* EOF */ +- } +- return -1; /* some other error */ ++ r = 0; /* EOF */ ++ goto done; + } + out[reedit] = 0; + if(scend+plen > (MAXLINE-2)) +@@ -346,7 +346,8 @@ int ed_emacsread(void *context, int fd,char *buff,int scend, int reedit) + case EOFCHAR: + ed_flush(ep->ed); + tty_cooked(ERRIO); +- return 0; ++ r = 0; ++ goto done; + #ifdef u370 + case cntl('S') : + case cntl('Q') : +@@ -752,8 +753,12 @@ process: + #endif /* SHOPT_MULTIBYTE */ + i = (int)strlen(buff); + if (i) +- return i; +- return -1; ++ r = i; ++done: ++ /* avoid leaving invalid pointers to destroyed automatic variables */ ++ Prompt = NULL; ++ drawbuff = ep->screen = ep->cursor = NULL; ++ return r; + } + + static void show_info(Emacs_t *ep,const char *str) +diff --git a/src/cmd/ksh93/edit/vi.c b/src/cmd/ksh93/edit/vi.c +index e95afa9..cea1204 100644 +--- a/src/cmd/ksh93/edit/vi.c ++++ b/src/cmd/ksh93/edit/vi.c +@@ -204,6 +204,7 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + { + Edit_t *ed = (Edit_t*)context; + int i; /* general variable */ ++ int r = -1; /* return value */ + Vi_t *vp = ed->e_vi; + char prompt[PRSIZE+2]; /* prompt */ + genchar Physical[2*MAXLINE]; /* physical image */ +@@ -211,6 +212,12 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + genchar ubuf[MAXLINE]; /* used for u command */ + genchar Window[MAXLINE]; /* window image */ + int Globals[9]; /* local global variables */ ++ ++ /*** Set raw mode ***/ ++ ++ if( tty_raw(ERRIO,0) < 0 ) ++ return reedit ? reedit : ed_read(context, fd, shbuf, nchar, 0); ++ + if(!vp) + { + ed->e_vi = vp = sh_newof(0,Vi_t,1,0); +@@ -225,16 +232,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + ed_setup(vp->ed,fd, reedit); + shbuf[reedit] = 0; + +- { +- /*** Set raw mode ***/ +- +- if(tty_raw(ERRIO,0) < 0 ) +- return reedit ? reedit : ed_read(context, fd, shbuf, nchar,0); +- i = last_virt-1; +- } +- + /*** Initialize some things ***/ + ++ i = last_virt-1; + virtual = (genchar*)shbuf; + #if SHOPT_MULTIBYTE + virtual = (genchar*)roundof((char*)virtual-(char*)0,sizeof(genchar)); +@@ -300,18 +300,9 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + } + virtual[0] = '\0'; + tty_cooked(ERRIO); +- +- switch(i) +- { +- case UEOF: +- /*** EOF ***/ +- return 0; +- +- case UINTR: +- /** interrupt **/ +- return -1; +- } +- return -1; ++ if (i == UEOF) ++ r = 0; /* EOF */ ++ goto done; + } + + /*** Get a line from the terminal ***/ +@@ -356,10 +347,13 @@ int ed_viread(void *context, int fd, char *shbuf, int nchar, int reedit) + if(vp->ed->nhlist) + ed_histlist(vp->ed,0); + #endif /* SHOPT_EDPREDICT */ +- return last_virt; ++ r = last_virt; + } +- else +- return -1; ++done: ++ /* avoid leaving invalid pointers to destroyed automatic variables */ ++ Prompt = NULL; ++ virtual = physical = window = vp->U_space = vp->u_space = NULL; ++ return r; + } + + +-- +2.49.0 + diff --git a/ksh-1.0.11-ssh-multibyte-long-paste.patch b/ksh-1.0.11-ssh-multibyte-long-paste.patch new file mode 100644 index 0000000..c6d34c9 --- /dev/null +++ b/ksh-1.0.11-ssh-multibyte-long-paste.patch @@ -0,0 +1,94 @@ +From 96d73c08a2786806f3def1fda66641b81e0af988 Mon Sep 17 00:00:00 2001 +From: SHIMIZU Akifumi +Date: Mon, 7 Apr 2025 19:47:16 +0900 +Subject: [PATCH] Fix long multibyte characters paste issue via ssh (#840) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When I paste long multibyte characters(over 80 byte) to ksh via +SSH, the characters are not displayed correctly. For example, the +following input demonstrates the issue. ja_JP.UTF-8 encoding is +used. + +Expected command line display: +$ echo "長い文字列を入れるとkshで文字列が乱れる場合があるようです" + +Actual command line display: +$ です"echo "長い文字列を入れるとkshで文字列が乱れる場合がある +...with the cursor over the 'e' in 'echo'. + +This issue appears to be caused by the ed_read() function splitting +a multibyte character sequence when reading into an 80-byte buffer. +This leads to incorrect character interpretation and display. + +Therefore, we edited the code to handle the case where the buffer +size is full in the middle of a multi-byte character. + +src/cmd/ksh93/sh/edit.c: +- putstack(): + - Before retrying to interpret a multibyte character in case of a + split due to end of buffer, restore the start position 'p'. + - Fix zeroing out errno = EILSEQ. +- ed_getchar(): Avoid a potential buffer overflow in 'readin'; + allow for an extra multibyte character, not merely an extra byte. + +Co-authored-by: Martijn Dekker +--- + src/cmd/ksh93/edit/edit.c | 13 ++++++++----- + 1 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c +index edfe4101e715..cc9f474695d8 100644 +--- a/src/cmd/ksh93/edit/edit.c ++++ b/src/cmd/ksh93/edit/edit.c +@@ -15,6 +15,7 @@ + * Johnothan King * + * Anuradha Weeraman * + * K. Eugene Carlson * ++* SHIMIZU Akifumi * + * * + ***********************************************************************/ + /* +@@ -764,6 +765,7 @@ static int putstack(Edit_t *ep,char string[], int nbyte, int type) + } + else + { ++ char *prevp = p; + again: + if((c=mbchar(p)) >=0) + { +@@ -771,19 +773,20 @@ static int putstack(Edit_t *ep,char string[], int nbyte, int type) + if(type) + c = -c; + } +-#ifdef EILSEQ +- else if(errno == EILSEQ) +- errno = 0; +-#endif + else if((endp-p) < mbmax()) + { ++ if(errno == EILSEQ) ++ errno = 0; + if ((c=ed_read(ep,ep->e_fd,endp, 1,0)) == 1) + { ++ p = prevp; + *++endp = 0; + goto again; + } + return c; + } ++ else if(errno == EILSEQ) ++ errno = 0; + else + { + ed_ringbell(); +@@ -833,7 +836,7 @@ static int putstack(Edit_t *ep,char string[], int nbyte, int type) + int ed_getchar(Edit_t *ep,int mode) + { + int n = 0, c; +- char readin[LOOKAHEAD+1]; ++ char *readin = fmtbuf(LOOKAHEAD + mbmax()); + if(!ep->e_lookahead) + { + ed_flush(ep); diff --git a/ksh-1.0.11-stty-noecho.patch b/ksh-1.0.11-stty-noecho.patch new file mode 100644 index 0000000..2fe543e --- /dev/null +++ b/ksh-1.0.11-stty-noecho.patch @@ -0,0 +1,77 @@ +From 4350174a5d4acabf78f97b28c6d0ae68ec703e78 Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Sun, 30 Mar 2025 00:14:35 +0000 +Subject: [PATCH] Fix 'stty -echo' in scripts (re: 41ebb55a) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Vincent Mihalkovič (@vmihalko) reports: +> In ksh versions later than v1.0.0-beta.1, setting stty -echo in a +> script no longer works as expected. This issue did not occur in +> earlier versions. +> +> I performed a git bisect between the last known good tag (reboot) +> and the first known bad tag (v1.0.0-beta.1). The regression was +> introduced in commit 41ebb55a. +> +> Reproducer: +> read a +> stty -echo +> read b +> +> Expected Behavior: +> • Input for a should be visible. +> • Input for b should not be echoed to the terminal. +> +> Actual Behavior: +> • Input for a is visible as expected. +> • Input for b is also visible, despite stty -echo being set. + +Analysis: + +The problem was that the tty_set(-1, 0, NULL) call below, which +invalidates saved terminal attributes, was no longer being executed +when running a script (note that job.jobcontrol is 0/false for +scripts). See edit.c for the tty_set function and what it does. + +src/cmd/ksh93/sh/jobs.c +1423: else if(job.jobcontrol) +1424: { +1425: if(pw->p_pid == tcgetpgrp(JOBTTY)) +1426: { +...skipped for brevity... +1430: } +1431: tty_set(-1, 0, NULL); +1432: } + +So, after running an external command such as stty, terminal +attributes that should have been invalidated were restored upon the +next 'read'. This was undoing the effect of the stty command. + +src/cmd/ksh93/sh/jobs.c: job_wait(): +- Move the test for job.jobcontrol so that saved terminal + attributes are again invalidated after running an external + command when job control for interactive shells is not active. + +Resolves: https://github.com/ksh93/ksh/issues/836 +--- + src/cmd/ksh93/sh/jobs.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c +index c65bc6e66094..513afb5582ab 100644 +--- a/src/cmd/ksh93/sh/jobs.c ++++ b/src/cmd/ksh93/sh/jobs.c +@@ -1420,9 +1420,9 @@ int job_wait(pid_t pid) + kill(sh.current_pid,SIGTSTP); + } + } +- else if(job.jobcontrol) ++ else + { +- if(pw->p_pid == tcgetpgrp(JOBTTY)) ++ if(job.jobcontrol && pw->p_pid == tcgetpgrp(JOBTTY)) + { + if(pw->p_pgrp==0) + pw->p_pgrp = pw->p_pid; diff --git a/ksh.spec b/ksh.spec index aad93d7..8765e9d 100644 --- a/ksh.spec +++ b/ksh.spec @@ -1,16 +1,21 @@ -%define anolis_release 2 +%define anolis_release 3 Name: ksh Summary: The Original ATT Korn Shell URL: http://www.kornshell.com/ +Source0: https://github.com/ksh93/ksh/archive/v1.0.10/ksh-1.0.10.tar.gz +Source1: kshcomp.conf +Source2: kshrc.rhs +Source3: dotkshrc License: EPL-2.0 Epoch: 3 -Version: 1.0.10 +Version: 1.0.10 Release: %{anolis_release}%{?dist} -Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz -Source1: kshcomp.conf -Source2: kshrc.rhs -Source3: dotkshrc +Patch1: ksh-1.0.11-segfault-sigwinch.patch +Patch2: ksh-1.0.11-redir.patch +Patch3: ksh-1.0.11-ssh-multibyte-long-paste.patch +Patch4: ksh-1.0.11-SHLVL.patch +Patch5: ksh-1.0.11-stty-noecho.patch Conflicts: pdksh Requires: coreutils, diffutils @@ -157,6 +162,17 @@ fi %doc README.md NEWS %changelog +* Wed Sep 17 2025 wenyuzifang - 3:1.0.10-8 +- Apply patch to fix crashes and instability when resizing terminals after 'stty -echo' + Resolves: RHEL-XXXXX +- Fix output loss and prevent shell hangs in command substitutions with redirections + Resolves: RHEL-XXXXX +- Fix garbled multibyte text display when pasting into ksh via SSH + Resolves: RHEL-XXXXX +- Prevent shell crashes when exec is used after unsetting SHLVL + Resolves: RHEL-XXXXX +- Fix terminal echo suppression in scripts to ensure stty -echo works correctly for secure input + Resolves: RHEL-XXXXX * Mon Jun 16 2025 Jessica Liu - 3:1.0.10-2 - Skip failed test on riscv64 -- Gitee