From deabf87f0cd580deaffdfa660d71d4a3d2f45395 Mon Sep 17 00:00:00 2001 From: lizhao2025 Date: Tue, 16 Dec 2025 19:25:24 +0800 Subject: [PATCH] Update code from upstream --- ksh-1.0.11-segfault-sigwinch.patch | 266 +++++++++++++++++++++++++++++ ksh.spec | 9 +- 2 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 ksh-1.0.11-segfault-sigwinch.patch diff --git a/ksh-1.0.11-segfault-sigwinch.patch b/ksh-1.0.11-segfault-sigwinch.patch new file mode 100644 index 0000000..1a6d641 --- /dev/null +++ b/ksh-1.0.11-segfault-sigwinch.patch @@ -0,0 +1,266 @@ +From b533bc2feb9a1b58b9cdb3a9f5bc94f4ff060a84 Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +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.spec b/ksh.spec index aad93d7..6aebb19 100644 --- a/ksh.spec +++ b/ksh.spec @@ -1,4 +1,4 @@ -%define anolis_release 2 +%define anolis_release 3 Name: ksh Summary: The Original ATT Korn Shell @@ -11,6 +11,7 @@ Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{ver Source1: kshcomp.conf Source2: kshrc.rhs Source3: dotkshrc +Patch0: ksh-1.0.11-segfault-sigwinch.patch Conflicts: pdksh Requires: coreutils, diffutils @@ -44,6 +45,7 @@ BuildArch: noarch The %{name}-doc package contains documentation files for %{name}. %prep +| %autosetup -p1 # /dev/fd test does not work because of mock @@ -157,6 +159,11 @@ fi %doc README.md NEWS %changelog +| +* Fri Mar 28 2025 Martijn Dekker - 3:1.0.10-3 +- Sync upstream changes from commit 1b767bc28817c7c722e9263f53360691f38ea621 +- Fix segfault upon SIGWINCH after 'stty -echo' (resolves RHEL-89866) + * Mon Jun 16 2025 Jessica Liu - 3:1.0.10-2 - Skip failed test on riscv64 -- Gitee