From 943f9a0b39abecddaaca4830c265fb04be332f48 Mon Sep 17 00:00:00 2001 From: wangyuhang Date: Thu, 7 Dec 2023 20:41:56 +0800 Subject: [PATCH] backport patches from upstream --- ...-Fix-handling-of-skipped-directories.patch | 120 +++++++++++++ backport-Fix-hist_nearend.patch | 51 ++++++ ...nteractive-restricted-shell-behavior.patch | 164 ++++++++++++++++++ ...with-not-loaded-autoloaded-functions.patch | 75 ++++++++ ksh.spec | 13 +- 5 files changed, 422 insertions(+), 1 deletion(-) create mode 100644 backport-Fix-handling-of-skipped-directories.patch create mode 100644 backport-Fix-hist_nearend.patch create mode 100644 backport-Fix-interactive-restricted-shell-behavior.patch create mode 100644 backport-functions-with-not-loaded-autoloaded-functions.patch diff --git a/backport-Fix-handling-of-skipped-directories.patch b/backport-Fix-handling-of-skipped-directories.patch new file mode 100644 index 0000000..e873f42 --- /dev/null +++ b/backport-Fix-handling-of-skipped-directories.patch @@ -0,0 +1,120 @@ +From a1e1592ac7028659d09eb3fa6c8a2227cba9f2a9 Mon Sep 17 00:00:00 2001 +From: Kurtis Rader +Date: Wed, 8 Jan 2020 19:14:31 -0800 +Subject: [PATCH] Fix handling of skipped directories + +The bug in `path_opentype()` fixed by this commit may affect other +scenarios but we know it affects autoloaded functions. Hence the unit +test for that scenario. + +Fixes #1454 + +(cherry picked from commit 3bc58164494eecc180e2bad966d7753bfdd1e295) +--- + src/cmd/ksh93/sh/path.c | 16 +++++++++------- + src/cmd/ksh93/tests/autoload.sh | 15 +++++++++++++++ + src/cmd/ksh93/tests/data/skipped_dir | 15 +++++++++++++++ + src/cmd/ksh93/tests/meson.build | 1 + + 4 files changed, 40 insertions(+), 7 deletions(-) + create mode 100644 src/cmd/ksh93/tests/autoload.sh + create mode 100644 src/cmd/ksh93/tests/data/skipped_dir + +diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c +index 69382f9..b7869b3 100644 +--- a/src/cmd/ksh93/sh/path.c ++++ b/src/cmd/ksh93/sh/path.c +@@ -475,28 +475,30 @@ Pathcomp_t *path_get(Shell_t *shp, const char *name) { + // + static_fn int path_opentype(Shell_t *shp, const char *name, Pathcomp_t *pp, int fun) { + int fd = -1; +- struct stat statb; +- Pathcomp_t *oldpp; + + if (!pp && !shp->pathlist) path_init(shp); + if (!fun && strchr(name, '/') && sh_isoption(shp, SH_RESTRICTED)) { + errormsg(SH_DICT, ERROR_exit(1), e_restricted, name); + __builtin_unreachable(); + } ++ ++ // The structure of this loop is slightly odd. It's a consequence of how path_nextcomp() works. ++ Pathcomp_t *next_pp = pp; + do { +- pp = path_nextcomp(shp, oldpp = pp, name, 0); +- while (oldpp && (oldpp->flags & PATH_SKIP)) oldpp = oldpp->next; +- if (fun && (!oldpp || !(oldpp->flags & PATH_FPATH))) continue; ++ pp = next_pp; ++ next_pp = path_nextcomp(shp, pp, name, NULL); ++ if (pp && (pp->flags & PATH_SKIP)) continue; ++ if (fun && (!pp || !(pp->flags & PATH_FPATH))) continue; + fd = sh_open(path_relative(shp, stkptr(shp->stk, PATH_OFFSET)), O_RDONLY | O_CLOEXEC, 0); ++ struct stat statb; + if (fd >= 0 && (fstat(fd, &statb) < 0 || S_ISDIR(statb.st_mode))) { + errno = EISDIR; + sh_close(fd); + fd = -1; + } +- } while (fd < 0 && pp); ++ } while (fd < 0 && next_pp); + + assert(fd < 0 || sh_iovalidfd(shp, fd)); +- + if (fd >= 0 && (fd = sh_iomovefd(shp, fd)) > 0) { + (void)fcntl(fd, F_SETFD, FD_CLOEXEC); + shp->fdstatus[fd] |= IOCLEX; +diff --git a/src/cmd/ksh93/tests/autoload.sh b/src/cmd/ksh93/tests/autoload.sh +new file mode 100644 +index 0000000..6aaa206 +--- /dev/null ++++ b/src/cmd/ksh93/tests/autoload.sh +@@ -0,0 +1,15 @@ ++# Verify the behavior of autoloaded functions. ++ ++# ==================== ++# Verify that directories in the path search list which should be skipped (e.g., because they don't ++# exist) interacts correctly with autoloaded functions. ++# ++# See https://github.com/att/ast/issues/1454 ++expect=$"Func cd called with |$TEST_DIR/usr|\n$TEST_DIR/usr" ++actual=$($SHELL "$TEST_ROOT/data/skipped_dir") ++actual_status=$? ++expect_status=0 ++[[ $actual_status == $expect_status ]] || ++ log_error "autoload function skipped dir test wrong status" "$expect_status" "$actual_status" ++[[ $actual == $expect ]] || ++ log_error "autoload function skipped dir test wrong output" "$expect" "$actual" +diff --git a/src/cmd/ksh93/tests/data/skipped_dir b/src/cmd/ksh93/tests/data/skipped_dir +new file mode 100644 +index 0000000..b8eeddc +--- /dev/null ++++ b/src/cmd/ksh93/tests/data/skipped_dir +@@ -0,0 +1,15 @@ ++# See https://github.com/att/ast/issues/1454 ++ ++mkdir -p "$TEST_DIR/usr/bin" ++print '#!/bin/sh' >"$TEST_DIR/usr/bin/cd" ++print 'builtin cd "$@"' >>"$TEST_DIR/usr/bin/cd" ++prefix="$TEST_DIR/ksh.$$" ++ ++FPATH="$prefix/bad:$prefix/functions" ++mkdir -p "$prefix/functions" ++print 'function cd { echo "Func cd called with |$*|"; command cd "$@"; }' >"$prefix/functions/cd" ++typeset -fu cd ++ ++PATH="/arglebargle:$PATH:$TEST_DIR/usr/bin:$TEST_DIR/bin" ++cd "$TEST_DIR/usr" ++pwd +diff --git a/src/cmd/ksh93/tests/meson.build b/src/cmd/ksh93/tests/meson.build +index 6a07d7c..26f2d43 100644 +--- a/src/cmd/ksh93/tests/meson.build ++++ b/src/cmd/ksh93/tests/meson.build +@@ -48,6 +48,7 @@ all_tests = [ + ['arrays'], + ['arrays2'], + ['attributes'], ++ ['autoload'], + ['basic', 90], + ['bracket'], + ['builtins'], +-- +1.8.3.1 + diff --git a/backport-Fix-hist_nearend.patch b/backport-Fix-hist_nearend.patch new file mode 100644 index 0000000..b95f3c6 --- /dev/null +++ b/backport-Fix-hist_nearend.patch @@ -0,0 +1,51 @@ +From a754ce08134f92c6f07e28ce7ec95f33135f2074 Mon Sep 17 00:00:00 2001 +From: Kurtis Rader +Date: Thu, 7 Nov 2019 17:48:40 -0800 +Subject: [PATCH] Fix hist_nearend() + +The original code, prior to the fix for issue #1271, called sfreserve() +with just the SF_LOCKR. While fixing the core issue of issue #1271 I +noticed the buffer did not have a read/write mode. Which is wrong. What +I didn't realize was that is equivalent to read+write. I incorrectly +included SF_WRITE rather than SF_RDWR. + +Fixes #1432 + +(cherry picked from commit b2e48a99ec6e2622c9e653bc64f334b2bdcff0f9) + +--- + CHANGELOG.md | 7 +++++++ + src/cmd/ksh93/edit/history.c | 2 +- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/CHANGELOG.md b/CHANGELOG.md +index 0f1fcaf3..0e38b780 100644 +--- a/CHANGELOG.md ++++ b/CHANGELOG.md +@@ -1,3 +1,10 @@ ++# ksh 2020.0.1 ++ ++## Notable fixes and improvements ++ ++- Fix `history` command behavior when the *~/.sh_history* file has ++ specific content (issue #1432). ++ + # ksh 2020.0.0 + + This documents changes since the AST code, which includes the `ksh` program, +diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c +index 50ac06a6..7c207c26 100644 +--- a/src/cmd/ksh93/edit/history.c ++++ b/src/cmd/ksh93/edit/history.c +@@ -365,7 +365,7 @@ static int hist_nearend(History_t *hp, Sfio_t *iop, off_t size) { + // Skip to marker command and return the number. Numbering commands occur after a null and begin + // with HIST_CMDNO. + while (true) { +- cp = buff = (unsigned char *)sfreserve(iop, SF_UNBOUND, SF_LOCKR | SF_WRITE); ++ cp = buff = (unsigned char *)sfreserve(iop, SF_UNBOUND, SF_LOCKR | SF_RDWR); + if (!cp) break; + + n = sfvalue(iop); +-- +2.19.1 + diff --git a/backport-Fix-interactive-restricted-shell-behavior.patch b/backport-Fix-interactive-restricted-shell-behavior.patch new file mode 100644 index 0000000..187514e --- /dev/null +++ b/backport-Fix-interactive-restricted-shell-behavior.patch @@ -0,0 +1,164 @@ +From c8a66c70b51f11bfcaeef22dd17b9b86ea1c3dfe Mon Sep 17 00:00:00 2001 +From: Kurtis Rader +Date: Tue, 21 Jan 2020 18:21:08 -0800 +Subject: [PATCH] Fix interactive restricted shell behavior + +Fixes #1459 + +(cherry picked from commit 1fd82bddfd36c8d381d4eb75bc1e6b2d4ccb6750) + +--- + scripts/create_rksh_symlink | 8 +++++ + src/cmd/ksh93/edit/edit.c | 2 ++ + src/cmd/ksh93/meson.build | 6 ++++ + src/cmd/ksh93/tests/meson.build | 6 ++-- + src/cmd/ksh93/tests/restricted.exp | 29 +++++++++++++++++++ + src/cmd/ksh93/tests/restricted.exp.out | 1 + + .../ksh93/tests/util/interactive.expect.rc | 1 + + 7 files changed, 51 insertions(+), 2 deletions(-) + create mode 100755 scripts/create_rksh_symlink + create mode 100644 src/cmd/ksh93/tests/restricted.exp + create mode 100644 src/cmd/ksh93/tests/restricted.exp.out + +diff --git a/scripts/create_rksh_symlink b/scripts/create_rksh_symlink +new file mode 100755 +index 00000000..03c013c4 +--- /dev/null ++++ b/scripts/create_rksh_symlink +@@ -0,0 +1,8 @@ ++#!/bin/sh ++# This is used by a Meson custom_target() to create a "rksh" symlink to the ++# "ksh" binary. This is slightly convoluted to support platforms, such as ++# Cygwin, where the ksh binary might have an extension such as ".exe". ++cmd=$(basename "$1") ++cd "$(dirname "$1")" || exit 1 ++rm -f "r$cmd" ++ln -s "$cmd" "r$cmd" +diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c +index 666719a9..9c62b1a7 100644 +--- a/src/cmd/ksh93/edit/edit.c ++++ b/src/cmd/ksh93/edit/edit.c +@@ -451,9 +451,11 @@ void ed_setup(Edit_t *ep, int fd, int reedit) { + if (!ep->e_term) ep->e_term = nv_search("TERM", shp->var_tree, 0); + if (ep->e_term && (term = nv_getval(ep->e_term)) && strlen(term) < sizeof(ep->e_termname) && + strcmp(term, ep->e_termname)) { ++ // Avoid an error from the 2>/dev/null redirection in a restricted shell. + bool r = sh_isoption(shp, SH_RESTRICTED); + if (r) sh_offoption(shp, SH_RESTRICTED); + sh_trap(shp, ".sh.subscript=$(tput cuu1 2>/dev/null)", 0); ++ if (r) sh_onoption(shp, SH_RESTRICTED); + pp = nv_getval(SH_SUBSCRNOD); + if (pp) { + // It should be impossible for the cursor up string to be truncated. +diff --git a/src/cmd/ksh93/meson.build b/src/cmd/ksh93/meson.build +index 491fb9b5..74ace1c7 100644 +--- a/src/cmd/ksh93/meson.build ++++ b/src/cmd/ksh93/meson.build +@@ -32,6 +32,11 @@ ksh93_exe = executable('ksh', ['sh/pmain.c'], c_args: shared_c_args, + dependencies: [libm_dep, libexecinfo_dep, libdl_dep], + install: true) + ++# Create a symlink for a restricted version of the ksh shell. ++create_rksh_symlink = find_program(source_dir + '/scripts/create_rksh_symlink') ++rksh93_exe = custom_target('rksh', input: ksh93_exe, output: 'rksh', build_by_default: true, ++ command: [create_rksh_symlink, '@INPUT@']) ++ + shcomp_exe = executable('shcomp', ['sh/shcomp.c'], c_args: shared_c_args, + include_directories: [configuration_incdir, ksh93_incdir], + link_with: [libksh, libast, libcmd, libdll], +@@ -47,6 +52,7 @@ test_driver = join_paths(test_dir, 'util', 'run_test.sh') + src_root = 'SRC_ROOT=' + source_dir + test_root = 'TEST_ROOT=' + test_dir + shell_var = 'SHELL=' + ksh93_exe.full_path() ++rshell_var = 'RSHELL=' + rksh93_exe.full_path() + shcomp_var = 'SHCOMP=' + shcomp_exe.full_path() + + libast_build_dir = join_paths(build_dir, 'src', 'lib', 'libast') +diff --git a/src/cmd/ksh93/tests/meson.build b/src/cmd/ksh93/tests/meson.build +index 26f2d43c..4f81ef3c 100644 +--- a/src/cmd/ksh93/tests/meson.build ++++ b/src/cmd/ksh93/tests/meson.build +@@ -81,6 +81,7 @@ all_tests = [ + ['readcsv'], + ['recttype'], + ['restricted'], ++ ['restricted.exp'], + ['rksh'], + ['select'], + ['sh_match', 120], +@@ -163,7 +164,8 @@ foreach testspec : all_tests + lang_var = 'LANG=en_US.UTF-8' + test(test_name, ksh93_exe, timeout: timeout, is_parallel: parallel, + args: [test_driver, test_name], +- env: [shell_var, lang_var, src_root, test_root, ld_library_path, libsample_path]) ++ env: [shell_var, lang_var, src_root, test_root, ld_library_path, libsample_path, ++ rshell_var]) + + # The shcomp variants are only applicable to the non-interactive tests. + if not test_name.endswith('.exp') +@@ -180,7 +182,7 @@ foreach testspec : all_tests + test(test_name + '/shcomp', ksh93_exe, timeout: timeout, is_parallel: parallel, + args: [ test_driver, 'shcomp', test_name], + env: [shell_var, lang_var, src_root, test_root, shcomp_var, ld_library_path, +- libsample_path]) ++ rshell_var, libsample_path]) + endif + endif + endif +diff --git a/src/cmd/ksh93/tests/restricted.exp b/src/cmd/ksh93/tests/restricted.exp +new file mode 100644 +index 00000000..4192675b +--- /dev/null ++++ b/src/cmd/ksh93/tests/restricted.exp +@@ -0,0 +1,29 @@ ++# vim: set filetype=expect: ++# ++# Interactive tests of restricted shell behavior. This is primarily to avoid regressions of ++# https://github.com/att/ast/issues/1459. It doesn't need to be a comprehensive test of restricted ++# shell behavior. That is already done in unit test restricted.sh. ++set pid [spawn $rksh] ++expect_prompt ++# Terminal rows and columns may default to zero so ensure sane values. ++send "stty rows 24 cols 80\r" ++expect_prompt ++ ++# ========== ++# Changing a restricted env var should be an error. ++log_test_entry ++send "PATH=/bin\r" ++expect -re ": PATH: restricted\r\n" { ++ puts "modifying PATH is restricted" ++} ++expect_prompt ++ ++# ========== ++# Exit the shell. ++log_test_entry ++send "\r" ++expect_prompt ++send [ctrl D] ++catch {expect default exp_continue} output ++log_debug "EOF output: $output" ++wait +diff --git a/src/cmd/ksh93/tests/restricted.exp.out b/src/cmd/ksh93/tests/restricted.exp.out +new file mode 100644 +index 00000000..d04d3921 +--- /dev/null ++++ b/src/cmd/ksh93/tests/restricted.exp.out +@@ -0,0 +1 @@ ++modifying PATH is restricted +diff --git a/src/cmd/ksh93/tests/util/interactive.expect.rc b/src/cmd/ksh93/tests/util/interactive.expect.rc +index dd039a21..f30e5e19 100644 +--- a/src/cmd/ksh93/tests/util/interactive.expect.rc ++++ b/src/cmd/ksh93/tests/util/interactive.expect.rc +@@ -6,6 +6,7 @@ log_user 0 + log_file -noappend interactive.tmp.log + + set ksh $env(SHELL) ++set rksh $env(RSHELL) + set timeout 2 + set send_human {.05 .1 5 .02 .2} + +-- +2.19.1 + diff --git a/backport-functions-with-not-loaded-autoloaded-functions.patch b/backport-functions-with-not-loaded-autoloaded-functions.patch new file mode 100644 index 0000000..2a42368 --- /dev/null +++ b/backport-functions-with-not-loaded-autoloaded-functions.patch @@ -0,0 +1,75 @@ +From a82279db9e49d2c42a95853f38061494df06e33c Mon Sep 17 00:00:00 2001 +From: Kurtis Rader +Date: Tue, 12 Nov 2019 19:45:34 -0800 +Subject: [PATCH] `functions` with not loaded autoloaded functions + +If there are functions marked to be autloaded, but not yet loaded, typing +`typeset -f` or `functions` dereferences a NULL pointer. + +Fixes #1436 + +(cherry picked from commit 7df11dedc5883fa2be1cf217ae6021cac56c81fa) + +--- + src/cmd/ksh93/bltins/typeset.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/cmd/ksh93/bltins/typeset.c b/src/cmd/ksh93/bltins/typeset.c +index 0862ace4..fba305f1 100644 +--- a/src/cmd/ksh93/bltins/typeset.c ++++ b/src/cmd/ksh93/bltins/typeset.c +@@ -716,7 +716,6 @@ int setall(char **argv, nvflag_t flag, Dt_t *troot, struct tdata *tp) { + static_fn int print_namval(Sfio_t *file, Namval_t *np, bool omit_attrs, struct tdata *tp) { + char *cp; + int indent = tp->indent, outname = 0, isfun; +- struct Ufunction *rp; + + sh_sigcheck(tp->sh); + if (tp->noref && nv_isref(np)) return 0; +@@ -749,11 +748,13 @@ static_fn int print_namval(Sfio_t *file, Namval_t *np, bool omit_attrs, struct t + } + } + if (isfun) { ++ struct Ufunction *rp = FETCH_VT(np->nvalue, rp); + Sfio_t *iop = NULL; + char *fname = NULL; ++ + if (nv_isattr(np, NV_NOFREE)) return 0; + if (!omit_attrs) { +- if (!FETCH_VT(np->nvalue, ip)) { ++ if (!rp) { + sfputr(file, "typeset -fu", ' '); + } else if (!nv_isattr(np, NV_FPOSIX)) { + sfputr(file, "function", ' '); +@@ -763,14 +764,16 @@ static_fn int print_namval(Sfio_t *file, Namval_t *np, bool omit_attrs, struct t + if (tp->wctname) cp += strlen(tp->wctname) + 1; + sfputr(file, cp, -1); + if (nv_isattr(np, NV_FPOSIX)) sfwrite(file, "()", 2); +- rp = FETCH_VT(np->nvalue, rp); ++ ++ // Has the function been defined in which case we know where it came from? Or just marked ++ // to be autoloaded in which case we know we can't print the definition of the function? + if (rp && rp->hoffset >= 0) { + fname = rp->fname; + } else { +- omit_attrs = false; ++ omit_attrs = true; + } ++ + if (omit_attrs) { +- rp = FETCH_VT(np->nvalue, rp); + if (tp->pflag && rp && rp->hoffset >= 0) { + sfprintf(file, " #line %d %s\n", rp->lineno, fname ? sh_fmtq(fname) : ""); + } else { +@@ -778,7 +781,7 @@ static_fn int print_namval(Sfio_t *file, Namval_t *np, bool omit_attrs, struct t + } + } else { + if (nv_isattr(np, NV_FTMP)) { +- fname = 0; ++ fname = NULL; + iop = tp->sh->heredocs; + } else if (fname) { + iop = sfopen(iop, fname, "r"); +-- +2.19.1 + diff --git a/ksh.spec b/ksh.spec index 5947cff..44aef1e 100644 --- a/ksh.spec +++ b/ksh.spec @@ -1,6 +1,6 @@ Name: ksh Version: 2020.0.0 -Release: 6 +Release: 7 Summary: The Original ATT Korn Shell License: EPL-1.0 URL: http://www.kornshell.com/ @@ -12,6 +12,11 @@ Source3: dotkshrc Patch1: CVE-2019-14868.patch +Patch6001: backport-Fix-hist_nearend.patch +Patch6002: backport-functions-with-not-loaded-autoloaded-functions.patch +Patch6003: backport-Fix-handling-of-skipped-directories.patch +Patch6004: backport-Fix-interactive-restricted-shell-behavior.patch + Provides: /bin/ksh /usr/bin/ksh BuildRequires: meson gcc glibc-devel ed Conflicts: pdksh @@ -84,6 +89,12 @@ done %config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf %changelog +* Thu Dec 7 2023 wangyuhang - 1:2020.0.0-7 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: backport patches from upstream + * Thu Apr 14 2022 renhongxun - 1:2020.0.0-6 - Type:bugfix - ID:NA -- Gitee