From e5c95b5de9782b92b3c7346265d824239e11496d Mon Sep 17 00:00:00 2001 From: eabdullin Date: Thu, 28 Mar 2024 10:40:15 +0000 Subject: [PATCH] import CS ksh-1.0.6-3.el9 --- .gitignore | 2 +- .ksh.metadata | 2 +- SOURCES/ksh-1.0.0-beta.1-regre-tests.patch | 365 ------------ .../ksh-1.0.0-beta.1-unset-PWD-segfault.patch | 151 ----- SOURCES/ksh-1.0.6-alarm-1.patch | 541 ++++++++++++++++++ SOURCES/ksh-1.0.6-alarm-2.patch | 162 ++++++ SOURCES/ksh-1.0.7-history-trim.patch | 99 ++++ SOURCES/ksh-1.0.7-segfault-strdup.patch | 58 ++ SPECS/ksh.spec | 53 +- 9 files changed, 897 insertions(+), 536 deletions(-) delete mode 100644 SOURCES/ksh-1.0.0-beta.1-regre-tests.patch delete mode 100644 SOURCES/ksh-1.0.0-beta.1-unset-PWD-segfault.patch create mode 100644 SOURCES/ksh-1.0.6-alarm-1.patch create mode 100644 SOURCES/ksh-1.0.6-alarm-2.patch create mode 100644 SOURCES/ksh-1.0.7-history-trim.patch create mode 100644 SOURCES/ksh-1.0.7-segfault-strdup.patch diff --git a/.gitignore b/.gitignore index 93c1e62..6f2c13e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ksh-1.0.0-beta.1.tar.gz +SOURCES/ksh-1.0.6.tar.gz diff --git a/.ksh.metadata b/.ksh.metadata index 9063777..def203b 100644 --- a/.ksh.metadata +++ b/.ksh.metadata @@ -1 +1 @@ -b22e526c9db91f9cab97af78f51b33b045a5c1e5 SOURCES/ksh-1.0.0-beta.1.tar.gz +9d3e1fb4406fa31a888a3599e1cfb54713df1e03 SOURCES/ksh-1.0.6.tar.gz diff --git a/SOURCES/ksh-1.0.0-beta.1-regre-tests.patch b/SOURCES/ksh-1.0.0-beta.1-regre-tests.patch deleted file mode 100644 index d9f8b46..0000000 --- a/SOURCES/ksh-1.0.0-beta.1-regre-tests.patch +++ /dev/null @@ -1,365 +0,0 @@ -From 541dd6f286a71c0d1d874807e61551026d03f409 Mon Sep 17 00:00:00 2001 -From: Vincent Mihalkovic -Date: Tue, 3 Aug 2021 10:20:04 +0200 -Subject: [PATCH] src/cmd/ksh93/tests: (temporary) disable failing tests - ---- - src/cmd/ksh93/tests/functions.sh | 2 ++ - src/cmd/ksh93/tests/io.sh | 2 ++ - src/cmd/ksh93/tests/leaks.sh | 49 ++++++++++++++++++++++++++++++-- - src/cmd/ksh93/tests/tilde.sh | 4 +-- - src/cmd/ksh93/tests/variables.sh | 2 ++ - 5 files changed, 54 insertions(+), 5 deletions(-) - -diff --git a/src/cmd/ksh93/tests/functions.sh b/src/cmd/ksh93/tests/functions.sh -index 731c1a6..43bb32a 100755 ---- a/src/cmd/ksh93/tests/functions.sh -+++ b/src/cmd/ksh93/tests/functions.sh -@@ -146,10 +146,12 @@ fi - if [[ $PWD != "$dir" ]] - then err_exit 'cd inside nested subshell changes $PWD' - fi -+: <<'disabled' # TODO: failing only on i686 arch - fun() "$bin_echo" hello - if [[ $(fun) != hello ]] - then err_exit one line functions not working - fi -+disabled - cat > $tmp/script <<-\! - print -r -- "$1" - ! -diff --git a/src/cmd/ksh93/tests/io.sh b/src/cmd/ksh93/tests/io.sh -index 2752145..f94c801 100755 ---- a/src/cmd/ksh93/tests/io.sh -+++ b/src/cmd/ksh93/tests/io.sh -@@ -241,7 +241,9 @@ then [[ $(3<#) -eq 0 ]] || err_exit "not at position 0" - read -u3 && err_exit "not found pattern not positioning at eof" - cat $tmp/seek | read -r <# *WWW* - [[ $REPLY == *WWWWW* ]] || err_exit '<# not working for pipes' -+: <<'disabled' # TODO: failing only on armv7, i686 arch. Reason: https://github.com/att/ast/commit/a5c692e1bd0d800e3f19be249d3170e69cbe001d - { < $tmp/seek <# ((2358336120)) ;} 2> /dev/null || err_exit 'long seek not working' -+disabled - else err_exit "$tmp/seek: cannot open for reading" - fi - redirect 3<&- || 'cannot close 3' -diff --git a/src/cmd/ksh93/tests/leaks.sh b/src/cmd/ksh93/tests/leaks.sh -index 0f50da2..6c8acfd 100755 ---- a/src/cmd/ksh93/tests/leaks.sh -+++ b/src/cmd/ksh93/tests/leaks.sh -@@ -109,6 +109,7 @@ do got=$($SHELL -c 'x=$(printf "%.*c" '$exp' x); print ${#x}' 2>&1) - [[ $got == $exp ]] || err_exit "large command substitution failed -- expected $exp, got $got" - done - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - data="(v=;sid=;di=;hi=;ti='1328244300';lv='o';id='172.3.161.178';var=(k='conn_num._total';u=;fr=;l='Number of Connections';n='22';t='number';))" - read -C stat <<< "$data" - for ((i=0; i < 8; i++)) # steady state first -@@ -122,8 +123,10 @@ done | while read -u$n -C stat - done {n}<&0- - after=$(getmem) - err_exit_if_leak "memory leak with read -C when deleting compound variable" -+disabled - - # extra 'read's to get to steady state -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - for ((i=0; i < 10; i++)) - do read -C stat <<< "$data" - done -@@ -133,10 +136,12 @@ do read -C stat <<< "$data" - done - after=$(getmem) - err_exit_if_leak "memory leak with read -C when using <<<" -+disabled - - # ====== - # Unsetting an associative array shouldn't cause a memory leak - # See https://www.mail-archive.com/ast-users@lists.research.att.com/msg01016.html -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - typeset -A stuff - before=$(getmem) - for (( i=0; i < N; i++ )) -@@ -152,6 +157,7 @@ done - unset stuff - after=$(getmem) - err_exit_if_leak 'unset of associative array causes memory leak' -+disabled - - # ====== - # Memory leak when resetting PATH and clearing hash table -@@ -167,17 +173,20 @@ done >/dev/null - after=$(getmem) - err_exit_if_leak 'memory leak on PATH reset before PATH search' - # ...test for another leak that only shows up when building with nmake: -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do PATH=/dev/null true # set/restore PATH & clear hash table - done >/dev/null - after=$(getmem) - err_exit_if_leak 'memory leak on PATH reset' -+disabled - - # ====== - # Defining a function in a virtual subshell - # https://github.com/ksh93/ksh/issues/114 - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - unset -f foo - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -186,7 +195,9 @@ done - after=$(getmem) - err_exit_if_leak 'ksh function defined in virtual subshell' - typeset -f foo >/dev/null && err_exit 'ksh function leaks out of subshell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - unset -f foo - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -195,9 +206,10 @@ done - after=$(getmem) - err_exit_if_leak 'POSIX function defined in virtual subshell' - typeset -f foo >/dev/null && err_exit 'POSIX function leaks out of subshell' -+disabled - - # Unsetting a function in a virtual subshell -- -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - function foo { echo bar; } - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -206,8 +218,11 @@ done - after=$(getmem) - err_exit_if_leak 'ksh function unset in virtual subshell' - typeset -f foo >/dev/null || err_exit 'ksh function unset in subshell was unset in main shell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - foo() { echo bar; } -+ - before=$(getmem) - for ((i=0; i < N; i++)) - do (unset -f foo) -@@ -215,24 +230,29 @@ done - after=$(getmem) - err_exit_if_leak 'POSIX function unset in virtual subshell' - typeset -f foo >/dev/null || err_exit 'POSIX function unset in subshell was unset in main shell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do (function foo { echo baz; }; unset -f foo) - done - after=$(getmem) - err_exit_if_leak 'ksh function defined and unset in virtual subshell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do (foo() { echo baz; }; unset -f foo) - done - after=$(getmem) - err_exit_if_leak 'POSIX function defined and unset in virtual subshell' -+disabled - - # ====== - # Sourcing a dot script in a virtual subshell -- -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - echo 'echo "$@"' > $tmp/dot.sh - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -240,6 +260,7 @@ do (. "$tmp/dot.sh" dot one two three >/dev/null) - done - after=$(getmem) - err_exit_if_leak 'script dotted in virtual subshell' -+disabled - - echo 'echo "$@"' > $tmp/dot.sh - before=$(getmem) -@@ -253,6 +274,8 @@ err_exit_if_leak 'script sourced in virtual subshell' - # Multiple leaks when using arrays in functions (Red Hat #921455) - # Fix based on: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik.patch - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs -+ - # TODO: both of these tests still leak (although much less after the patch) when run in a non-C locale. - saveLANG=$LANG; LANG=C # comment out to test remaining leak (1/2) - -@@ -268,7 +291,9 @@ do _hash - done - after=$(getmem) - err_exit_if_leak 'associative array in function' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - function _array - { - typeset w=(1 31534 42) -@@ -283,12 +308,13 @@ after=$(getmem) - err_exit_if_leak 'indexed array in function' - - LANG=$saveLANG # comment out to test remaining leak (2/2) -+disabled - - # ====== - # Memory leak in typeset (Red Hat #1036470) - # Fix based on: https://src.fedoraproject.org/rpms/ksh/blob/642af4d6/f/ksh-20120801-memlik3.patch - # The fix was backported from ksh 93v- beta. -- -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - function myFunction - { - typeset toPrint="something" -@@ -301,10 +327,12 @@ do state=$(myFunction) - done - after=$(getmem) - err_exit_if_leak 'typeset in function called by command substitution' -+disabled - - # ====== - # Check that unsetting an alias frees both the node and its value - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do alias "test$i=command$i" -@@ -312,10 +340,12 @@ do alias "test$i=command$i" - done - after=$(getmem) - err_exit_if_leak 'unalias' -+disabled - - # ====== - # Red Hat bug rhbz#982142: command substitution leaks - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - # case1: Nested command substitutions - # (reportedly already fixed in 93u+, but let's keep the test) - before=$(getmem) -@@ -324,8 +354,10 @@ do a=`true 1 + \`true 1 + 1\`` # was: a=`expr 1 + \`expr 1 + 1\`` - done - after=$(getmem) - err_exit_if_leak 'nested command substitutions' -+disabled - - # case2: Command alias -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - alias ls='true -ltr' # was: alias ls='ls -ltr' - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -334,8 +366,10 @@ done - after=$(getmem) - unalias ls - err_exit_if_leak 'alias in command substitution' -+disabled - - # case3: Function call via autoload -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - cat >$tmp/func1 <<\EOF - function func1 - { -@@ -353,12 +387,14 @@ after=$(getmem) - unset -f func1 - unset -v FPATH - err_exit_if_leak 'function call via autoload in command substitution' -+disabled - - # ====== - - # add some random utilities to the hash table to detect memory leak on hash table reset when changing PATH - random_utils=(chmod cp mv awk sed diff comm cut sort uniq date env find mkdir rmdir pr sleep) - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - save_PATH=$PATH - hash "${random_utils[@]}" - before=$(getmem) -@@ -368,7 +404,9 @@ do hash -r - done - after=$(getmem) - err_exit_if_leak 'clear hash table (hash -r) in main shell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do PATH=/dev/null -@@ -377,13 +415,16 @@ do PATH=/dev/null - done - after=$(getmem) - err_exit_if_leak 'set PATH value in main shell' -+disabled - -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - before=$(getmem) - for ((i=0; i < N; i++)) - do PATH=/dev/null command true - done - after=$(getmem) - err_exit_if_leak 'run command with preceding PATH assignment in main shell' -+disabled - - : <<'disabled' # TODO: known leak (approx 73552 bytes after 512 iterations) - before=$(getmem) -@@ -454,6 +495,7 @@ disabled - - # ====== - # Test for a memory leak after 'cd' (in relation to $PWD and $OLDPWD) -+: <<'disabled' # TODO: upstream, leak sometimes on some archs - original_pwd=$PWD - before=$(getmem) - for ((i=0; i < N; i++)) -@@ -473,6 +515,7 @@ done - after=$(getmem) - err_exit_if_leak 'PWD and/or OLDPWD changed by cd' - cd $original_pwd -+disabled - - # ====== - # https://github.com/ksh93/ksh/issues/253#issuecomment-815308466 -diff --git a/src/cmd/ksh93/tests/tilde.sh b/src/cmd/ksh93/tests/tilde.sh -index 1be00b9..1de0b16 100755 ---- a/src/cmd/ksh93/tests/tilde.sh -+++ b/src/cmd/ksh93/tests/tilde.sh -@@ -151,13 +151,13 @@ do ( - [[ $got == "$exp" ]] || err_exit "$disc discipline: counter:" \ - "expected $(printf %q "$exp"), got $(printf %q "$got")" - ((i==5)) || err_exit "$disc discipline: counter: $i != 5" -- -+: << 'disabled' # TODO sometimes fails on armv7 arch - set -- ~spc ~spc ~spc - got=$#,$1,$2,$3 - exp=$'3,one\ttwo three\n\tfour,one\ttwo three\n\tfour,one\ttwo three\n\tfour' - [[ $got == "$exp" ]] || err_exit "$disc discipline: quoting of whitespace:" \ - "expected $(printf %q "$exp"), got $(printf %q "$got")" -- -+disabled - print "$Errors" >$tmp/Errors - ) & - wait "$!" 2>crashmsg -diff --git a/src/cmd/ksh93/tests/variables.sh b/src/cmd/ksh93/tests/variables.sh -index 253f84a..8b306a1 100755 ---- a/src/cmd/ksh93/tests/variables.sh -+++ b/src/cmd/ksh93/tests/variables.sh -@@ -58,6 +58,7 @@ rand2=$($SHELL -c 'RANDOM=1; (echo $RANDOM)') - (( rand1 == rand2 )) && err_exit "Test 3: \$RANDOM seed in subshell doesn't change" \ - "(both results are $rand1)" - # $RANDOM should be reseeded for the ( simple_command & ) optimization -+: <<'disabled' # Reason: On slower systems it could fail with an arithmetic syntax error because the output was verified before it had been written. From: https://github.com/ksh93/ksh/commit/33269cae615c913592e776276b480bf1d722ff07 - ( echo $RANDOM & ) >r1 - ( echo $RANDOM & ) >r2 - integer giveup=0 -@@ -74,6 +75,7 @@ fi - kill $! 2>/dev/null - trap - USR1 - unset giveup -+disabled - # Virtual subshells should not influence the parent shell's RANDOM sequence - RANDOM=456 - exp="$RANDOM $RANDOM $RANDOM $RANDOM $RANDOM" --- -2.31.1 - diff --git a/SOURCES/ksh-1.0.0-beta.1-unset-PWD-segfault.patch b/SOURCES/ksh-1.0.0-beta.1-unset-PWD-segfault.patch deleted file mode 100644 index 9db8293..0000000 --- a/SOURCES/ksh-1.0.0-beta.1-unset-PWD-segfault.patch +++ /dev/null @@ -1,151 +0,0 @@ -diff --git a/src/cmd/ksh93/bltins/cd_pwd.c b/src/cmd/ksh93/bltins/cd_pwd.c -index e441805..715171c 100644 ---- a/src/cmd/ksh93/bltins/cd_pwd.c -+++ b/src/cmd/ksh93/bltins/cd_pwd.c -@@ -91,8 +91,6 @@ int b_cd(int argc, char *argv[],Shbltin_t *context) - oldpwd = path_pwd(shp,0); - opwdnod = sh_scoped(shp,OLDPWDNOD); - pwdnod = sh_scoped(shp,PWDNOD); -- if(oldpwd == e_dot && pwdnod->nvalue.cp) -- oldpwd = (char*)pwdnod->nvalue.cp; /* if path_pwd() failed to get the pwd, use $PWD */ - if(shp->subshell) - { - opwdnod = sh_assignok(opwdnod,1); -@@ -116,7 +114,7 @@ int b_cd(int argc, char *argv[],Shbltin_t *context) - if(shp->subshell && !shp->subshare) - { - #if _lib_fchdir -- if(!test_inode(nv_getval(pwdnod),e_dot)) -+ if(!test_inode(shp->pwd,e_dot)) - #endif - sh_subfork(); - } -@@ -221,6 +219,7 @@ success: - if(*dp && (*dp!='.'||dp[1]) && strchr(dir,'/')) - sfputr(sfstdout,dir,'\n'); - nv_putval(opwdnod,oldpwd,NV_RDONLY); -+ free((void*)shp->pwd); - if(*dir == '/') - { - flag = strlen(dir); -@@ -229,16 +228,12 @@ success: - dir[flag] = 0; - nv_putval(pwdnod,dir,NV_RDONLY); - nv_onattr(pwdnod,NV_EXPORT); -- if(shp->pwd) -- free((void*)shp->pwd); -- shp->pwd = sh_strdup(pwdnod->nvalue.cp); -+ shp->pwd = sh_strdup(dir); - } - else - { - /* pathcanon() failed to canonicalize the directory, which happens when 'cd' is invoked from a - nonexistent PWD with a relative path as the argument. Reinitialize $PWD as it will be wrong. */ -- if(shp->pwd) -- free((void*)shp->pwd); - shp->pwd = NIL(const char*); - path_pwd(shp,0); - if(*shp->pwd != '/') -@@ -279,7 +274,7 @@ int b_pwd(int argc, char *argv[],Shbltin_t *context) - errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0)); - UNREACHABLE(); - } -- if(*(cp = path_pwd(shp,0)) != '/') -+ if(*(cp = path_pwd(shp,0)) != '/' || !test_inode(cp,e_dot)) - { - errormsg(SH_DICT,ERROR_system(1), e_pwd); - UNREACHABLE(); -diff --git a/src/cmd/ksh93/data/msg.c b/src/cmd/ksh93/data/msg.c -index 5cec66d..ee44e81 100644 ---- a/src/cmd/ksh93/data/msg.c -+++ b/src/cmd/ksh93/data/msg.c -@@ -82,7 +82,7 @@ const char e_badpattern[] = "%s: invalid shell pattern"; - const char e_noread[] = "%s: pattern seek requires read access"; - const char e_logout[] = "Use 'exit' to terminate this shell"; - const char e_exec[] = "%s: cannot execute"; --const char e_pwd[] = "cannot access parent directories"; -+const char e_pwd[] = "determine present working directory"; - const char e_found[] = "%s: not found"; - #ifdef ENAMETOOLONG - const char e_toolong[] = "%s: file name too long"; -diff --git a/src/cmd/ksh93/sh/path.c b/src/cmd/ksh93/sh/path.c -index eb18d8c..c097b5f 100644 ---- a/src/cmd/ksh93/sh/path.c -+++ b/src/cmd/ksh93/sh/path.c -@@ -249,7 +249,12 @@ char *path_pwd(Shell_t *shp,int flag) - NOT_USED(flag); - /* Don't bother if PWD already set */ - if(shp->pwd) -- return((char*)shp->pwd); -+ { -+ if(*shp->pwd=='/') -+ return((char*)shp->pwd); -+ free((void*)shp->pwd); -+ -+ } - /* First see if PWD variable is correct */ - pwdnod = sh_scoped(shp,PWDNOD); - cp = nv_getval(pwdnod); -@@ -261,22 +266,29 @@ char *path_pwd(Shell_t *shp,int flag) - cp = nv_getval(sh_scoped(shp,HOME)); - if(!(cp && *cp=='/' && test_inode(cp,e_dot))) - { -- /* Get physical PWD (no symlinks) using getcwd(3), fall back to "." */ -+ /* Get physical PWD (no symlinks) using getcwd(3) */ - cp = getcwd(NIL(char*),0); -- if(!cp) -- return((char*)e_dot); -- tofree++; -+ if(cp) -+ tofree++; - } - /* Store in PWD variable */ -- if(shp->subshell) -- pwdnod = sh_assignok(pwdnod,1); -- nv_putval(pwdnod,cp,NV_RDONLY); -+ if(cp) -+ { -+ if(shp->subshell) -+ pwdnod = sh_assignok(pwdnod,1); -+ nv_putval(pwdnod,cp,NV_RDONLY); -+ } - if(tofree) -- free(cp); -+ free((void*)cp); - } - nv_onattr(pwdnod,NV_EXPORT); -+ /* Neither obtained the pwd nor can fall back to sane-ish $PWD: fall back to "." */ -+ if(!cp) -+ cp = nv_getval(pwdnod); -+ if(!cp || *cp!='/') -+ nv_putval(pwdnod,cp=(char*)e_dot,NV_RDONLY); - /* Set shell PWD */ -- shp->pwd = sh_strdup(pwdnod->nvalue.cp); -+ shp->pwd = sh_strdup(cp); - return((char*)shp->pwd); - } - -diff --git a/src/cmd/ksh93/tests/path.sh b/src/cmd/ksh93/tests/path.sh -index 4b2a97d..2da7d1f 100755 ---- a/src/cmd/ksh93/tests/path.sh -+++ b/src/cmd/ksh93/tests/path.sh -@@ -902,5 +902,19 @@ got=$? - [[ $exp == $got ]] || err_exit "Test 7E: exit status or error message for exec'd command with long name wrong" \ - "(expected $exp, got $got)" - -+# ====== -+# Crash after unsetting PWD -+(unset PWD; (cd /); :) & # the : avoids optimizing out the subshell -+wait "$!" 2>/dev/null -+((!(e = $?))) || err_exit "shell crashes on 'cd' in subshell exit with unset PWD" \ -+ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))" -+mkdir "$tmp/testdir" -+cd "$tmp/testdir" -+"$SHELL" -c 'cd /; rmdir "$1"' x "$tmp/testdir" -+(unset PWD; exec "$SHELL" -c '(cd /); :') & -+wait "$!" 2>/dev/null -+((!(e = $?))) || err_exit 'shell crashes on failure obtain the PWD on init' \ -+ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"))" -+ - # ====== - exit $((Errors<125?Errors:125)) diff --git a/SOURCES/ksh-1.0.6-alarm-1.patch b/SOURCES/ksh-1.0.6-alarm-1.patch new file mode 100644 index 0000000..7e18055 --- /dev/null +++ b/SOURCES/ksh-1.0.6-alarm-1.patch @@ -0,0 +1,541 @@ +diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile +index f6e6ac8..9d72d87 100644 +--- a/src/cmd/ksh93/Mamfile ++++ b/src/cmd/ksh93/Mamfile +@@ -220,30 +220,18 @@ make install + done pmain.o generated + make libshell.a archive + prev shell.req +- make cd_pwd.o +- make bltins/cd_pwd.c +- make include/test.h implicit +- prev include/shtable.h implicit +- make include/defs.h implicit +- prev include/regress.h implicit dontcare +- prev include/shtable.h +- prev include/shell.h +- prev ${PACKAGE_ast_INCLUDE}/endian.h +- prev include/name.h +- prev include/argnod.h implicit +- prev ${PACKAGE_ast_INCLUDE}/cdt.h +- prev ${PACKAGE_ast_INCLUDE}/error.h +- prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ make alarm.o ++ make bltins/alarm.c ++ make FEATURE/time implicit ++ prev features/time ++ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time ++ make ${PACKAGE_ast_INCLUDE}/times.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit + prev ${PACKAGE_ast_INCLUDE}/ast.h +- done include/defs.h +- done include/test.h +- make ${PACKAGE_ast_INCLUDE}/ls.h implicit +- prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit dontcare +- prev ${PACKAGE_ast_INCLUDE}/ast_fs.h +- prev ${PACKAGE_ast_INCLUDE}/ast_std.h +- done ${PACKAGE_ast_INCLUDE}/ls.h ++ done ${PACKAGE_ast_INCLUDE}/times.h ++ done FEATURE/time generated + make include/builtins.h implicit +- prev include/shtable.h ++ prev include/shtable.h implicit + make FEATURE/dynamic implicit + prev features/dynamic + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/dynamic +@@ -251,6 +239,36 @@ make install + done FEATURE/dynamic generated + prev ${PACKAGE_ast_INCLUDE}/option.h + done include/builtins.h ++ prev ${PACKAGE_ast_INCLUDE}/error.h ++ make include/defs.h implicit ++ prev include/regress.h implicit ++ prev include/shtable.h ++ prev include/shell.h ++ prev ${PACKAGE_ast_INCLUDE}/endian.h ++ prev include/name.h ++ prev include/argnod.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/cdt.h ++ prev FEATURE/externs ++ prev ${PACKAGE_ast_INCLUDE}/error.h ++ prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/defs.h ++ prev shopt.h ++ done bltins/alarm.c ++ exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c bltins/alarm.c ++ done alarm.o generated ++ make cd_pwd.o ++ make bltins/cd_pwd.c ++ make include/test.h implicit ++ prev include/shtable.h ++ prev include/defs.h ++ done include/test.h ++ make ${PACKAGE_ast_INCLUDE}/ls.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_mode.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast_fs.h ++ prev ${PACKAGE_ast_INCLUDE}/ast_std.h ++ done ${PACKAGE_ast_INCLUDE}/ls.h ++ prev include/builtins.h + prev include/name.h + make include/path.h implicit + make FEATURE/acct implicit +@@ -341,14 +359,7 @@ make install + make misc.o + make bltins/misc.c + prev ${PACKAGE_ast_INCLUDE}/times.h +- make FEATURE/time implicit +- prev features/time +- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time +- make ${PACKAGE_ast_INCLUDE}/times.h implicit +- prev ${PACKAGE_ast_INCLUDE}/ast_time.h implicit dontcare +- prev ${PACKAGE_ast_INCLUDE}/ast.h +- done ${PACKAGE_ast_INCLUDE}/times.h dontcare +- done FEATURE/time generated ++ prev FEATURE/time + prev FEATURE/locale + make include/jobs.h implicit + prev ${PACKAGE_ast_INCLUDE}/vmalloc.h +@@ -1175,7 +1186,7 @@ make install + done edit/hexpand.c + exec - ${CC} ${mam_cc_FLAGS} ${CCFLAGS} -I. -Iinclude -I${PACKAGE_ast_INCLUDE} -D_API_ast=20100309 -DERROR_CONTEXT_T=Error_context_t -c edit/hexpand.c + done hexpand.o generated +- exec - ${AR} rc libshell.a cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o ++ exec - ${AR} rc libshell.a alarm.o cd_pwd.o cflow.o enum.o getopts.o hist.o misc.o mkservice.o print.o read.o sleep.o trap.o test.o typeset.o ulimit.o umask.o whence.o main.o nvdisc.o nvtype.o arith.o args.o array.o completion.o defs.o edit.o expand.o regress.o fault.o fcin.o + exec - ${AR} rc libshell.a history.o init.o io.o jobs.o lex.o macro.o name.o nvtree.o parse.o path.o string.o streval.o subshell.o tdump.o timers.o trestore.o waitevent.o xec.o limits.o msg.o strdata.o testops.o keywords.o options.o signals.o aliases.o builtins.o variables.o lexstates.o emacs.o vi.o hexpand.o + exec - (ranlib libshell.a) >/dev/null 2>&1 || true + done libshell.a generated +diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c +new file mode 100644 +index 0000000..f31bed7 +--- /dev/null ++++ b/src/cmd/ksh93/bltins/alarm.c +@@ -0,0 +1,277 @@ ++/*********************************************************************** ++* * ++* This software is part of the ast package * ++* Copyright (c) 1982-2012 AT&T Intellectual Property * ++* Copyright (c) 2020-2023 Contributors to ksh 93u+m * ++* and is licensed under the * ++* Eclipse Public License, Version 2.0 * ++* * ++* A copy of the License is available at * ++* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html * ++* (with md5 checksum 84283fa8859daf213bdda5a9f8d1be1d) * ++* * ++* David Korn * ++* Martijn Dekker * ++* Johnothan King * ++* * ++***********************************************************************/ ++/* ++ * alarm [-r] [varname [+]when] ++ * ++ * David Korn ++ * AT&T Labs ++ * ++ */ ++ ++/* ++ * TODO: 2014 email from David Korn cited at : ++ * ++ * > I never documented the alarm builtin because it is problematic. The ++ * > problem is that traps can't safely be handled asynchronously. What should ++ * > happen is that the trap is marked for execution (sh.trapnote) and run after ++ * > the current command completes. The time trap should wake up the shell if ++ * > it is blocked and it should return and then handle the trap. ++ */ ++ ++#include "shopt.h" ++#include "defs.h" ++#include ++#include "builtins.h" ++#include "FEATURE/time" ++ ++#define R_FLAG 1 ++#define L_FLAG 2 ++ ++struct tevent ++{ ++ Namfun_t fun; ++ Namval_t *node; ++ Namval_t *action; ++ struct tevent *next; ++ long milli; ++ int flags; ++ void *timeout; ++}; ++ ++static const char ALARM[] = "alarm"; ++ ++static void trap_timeout(void*); ++ ++/* ++ * insert timeout item on current given list in sorted order ++ */ ++static void *time_add(struct tevent *item, void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ if(!tp || item->milli < tp->milli) ++ { ++ item->next = tp; ++ list = item; ++ } ++ else ++ { ++ while(tp->next && item->milli > tp->next->milli) ++ tp = tp->next; ++ item->next = tp->next; ++ tp->next = item; ++ } ++ tp = item; ++ tp->timeout = sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,tp); ++ return list; ++} ++ ++/* ++ * delete timeout item from current given list, delete timer ++ */ ++static void *time_delete(struct tevent *item, void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ if(item==tp) ++ list = tp->next; ++ else ++ { ++ while(tp && tp->next != item) ++ tp = tp->next; ++ if(tp) ++ tp->next = item->next; ++ } ++ if(item->timeout) ++ sh_timerdel(item->timeout); ++ return list; ++} ++ ++static void print_alarms(void *list) ++{ ++ struct tevent *tp = (struct tevent*)list; ++ while(tp) ++ { ++ if(tp->timeout) ++ { ++ char *name = nv_name(tp->node); ++ if(tp->flags&R_FLAG) ++ { ++ double d = tp->milli; ++ sfprintf(sfstdout,e_alrm1,name,d/1000.); ++ } ++ else ++ sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node)); ++ } ++ tp = tp->next; ++ } ++} ++ ++static void trap_timeout(void* handle) ++{ ++ struct tevent *tp = (struct tevent*)handle; ++ sh.trapnote |= SH_SIGALRM; ++ if(!(tp->flags&R_FLAG)) ++ tp->timeout = 0; ++ tp->flags |= L_FLAG; ++ sh.sigflag[SIGALRM] |= SH_SIGALRM; ++ if(sh_isstate(SH_TTYWAIT)) ++ sh_timetraps(); ++} ++ ++void sh_timetraps(void) ++{ ++ struct tevent *tp, *tpnext; ++ struct tevent *tptop; ++ while(1) ++ { ++ sh.sigflag[SIGALRM] &= ~SH_SIGALRM; ++ tptop= (struct tevent*)sh.st.timetrap; ++ for(tp=tptop;tp;tp=tpnext) ++ { ++ tpnext = tp->next; ++ if(tp->flags&L_FLAG) ++ { ++ tp->flags &= ~L_FLAG; ++ if(tp->action) ++ sh_fun(tp->action,tp->node,NULL); ++ tp->flags &= ~L_FLAG; ++ if(!tp->flags) ++ nv_unset(tp->node); ++ } ++ } ++ if(!(sh.sigflag[SIGALRM]&SH_SIGALRM)) ++ break; ++ } ++} ++ ++ ++/* ++ * This trap function catches "alarm" actions only ++ */ ++static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t *fp) ++{ ++ struct tevent *tp = (struct tevent*)fp; ++ if(!event) ++ return action ? Empty : (char*)ALARM; ++ if(strcmp(event,ALARM)!=0) ++ { ++ /* try the next level */ ++ return nv_setdisc(np, event, action, fp); ++ } ++ if(action==np) ++ action = tp->action; ++ else ++ tp->action = action; ++ return action ? (char*)action : Empty; ++} ++ ++/* ++ * catch assignments and set alarm traps ++ */ ++static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp) ++{ ++ struct tevent *tp = (struct tevent*)fp; ++ double d; ++ if(val) ++ { ++ double now; ++#ifdef timeofday ++ struct timeval tmp; ++ timeofday(&tmp); ++ now = tmp.tv_sec + 1.e-6*tmp.tv_usec; ++#else ++ now = (double)time(NULL); ++#endif /* timeofday */ ++ nv_putv(np,val,flag,fp); ++ d = nv_getnum(np); ++ if(*val=='+') ++ { ++ double x = d + now; ++ nv_putv(np,(char*)&x,NV_INTEGER|NV_DOUBLE,fp); ++ } ++ else ++ d -= now; ++ tp->milli = 1000*(d+.0005); ++ if(tp->timeout) ++ sh.st.timetrap = time_delete(tp,sh.st.timetrap); ++ if(tp->milli > 0) ++ sh.st.timetrap = time_add(tp,sh.st.timetrap); ++ } ++ else ++ { ++ tp = (struct tevent*)nv_stack(np, NULL); ++ sh.st.timetrap = time_delete(tp,sh.st.timetrap); ++ nv_unset(np); ++ free(fp); ++ } ++} ++ ++static const Namdisc_t alarmdisc = ++{ ++ sizeof(struct tevent), ++ putval, ++ 0, ++ 0, ++ setdisc, ++}; ++ ++int b_alarm(int argc,char *argv[],Shbltin_t *context) ++{ ++ int n,rflag=0; ++ Namval_t *np; ++ struct tevent *tp; ++ while (n = optget(argv, sh_optalarm)) switch (n) ++ { ++ case 'r': ++ rflag = R_FLAG; ++ break; ++ case ':': ++ errormsg(SH_DICT,2, "%s", opt_info.arg); ++ break; ++ case '?': ++ errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); ++ UNREACHABLE(); ++ } ++ argc -= opt_info.index; ++ argv += opt_info.index; ++ if(error_info.errors) ++ { ++ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); ++ UNREACHABLE(); ++ } ++ if(argc==0) ++ { ++ print_alarms(sh.st.timetrap); ++ return 0; ++ } ++ if(argc!=2) ++ { ++ errormsg(SH_DICT,ERROR_usage(2),optusage(NULL)); ++ UNREACHABLE(); ++ } ++ np = nv_open(argv[0],sh.var_tree,NV_NOARRAY|NV_VARNAME); ++ if(!nv_isnull(np)) ++ nv_unset(np); ++ nv_setattr(np, NV_DOUBLE); ++ tp = sh_newof(NULL,struct tevent,1,0); ++ tp->fun.disc = &alarmdisc; ++ tp->flags = rflag; ++ tp->node = np; ++ nv_stack(np,(Namfun_t*)tp); ++ nv_putval(np, argv[1], 0); ++ return 0; ++} +diff --git a/src/cmd/ksh93/bltins/sleep.c b/src/cmd/ksh93/bltins/sleep.c +index b34e62d..3bb55b1 100644 +--- a/src/cmd/ksh93/bltins/sleep.c ++++ b/src/cmd/ksh93/bltins/sleep.c +@@ -127,6 +127,8 @@ skip: + if(tloc < (now=time(NULL))) + break; + d = (double)(tloc-now); ++ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) ++ sh_timetraps(); + } + return 0; + } +diff --git a/src/cmd/ksh93/data/builtins.c b/src/cmd/ksh93/data/builtins.c +index 760b7ce..22ea156 100644 +--- a/src/cmd/ksh93/data/builtins.c ++++ b/src/cmd/ksh93/data/builtins.c +@@ -116,6 +116,7 @@ const struct shtable3 shtab_builtins[] = + "pwd", NV_BLTIN|BLT_ENV, bltin(pwd), + "read", NV_BLTIN|BLT_ENV, bltin(read), + "sleep", NV_BLTIN, bltin(sleep), ++ "alarm", NV_BLTIN|BLT_ENV, bltin(alarm), + "times", NV_BLTIN|BLT_ENV|BLT_SPC, bltin(times), + "ulimit", NV_BLTIN|BLT_ENV, bltin(ulimit), + "umask", NV_BLTIN|BLT_ENV, bltin(umask), +@@ -2170,6 +2171,8 @@ const char sh_optwhence[] = + ; + + ++const char e_alrm1[] = "alarm -r %s +%.3g\n"; ++const char e_alrm2[] = "alarm %s %.3f\n"; + const char e_baddisc[] = "%s: invalid discipline function"; + const char e_nofork[] = "cannot fork"; + const char e_nosignal[] = "%s: unknown signal name"; +diff --git a/src/cmd/ksh93/include/builtins.h b/src/cmd/ksh93/include/builtins.h +index 34c697c..f6b3f59 100644 +--- a/src/cmd/ksh93/include/builtins.h ++++ b/src/cmd/ksh93/include/builtins.h +@@ -115,6 +115,8 @@ extern int b_times(int, char*[],Shbltin_t*); + + extern short b_enum_nelem(Namfun_t*); + ++extern const char e_alrm1[]; ++extern const char e_alrm2[]; + extern const char e_badfun[]; + extern const char e_baddisc[]; + extern const char e_nofork[]; +diff --git a/src/cmd/ksh93/include/defs.h b/src/cmd/ksh93/include/defs.h +index 306ea7e..b5bfb67 100644 +--- a/src/cmd/ksh93/include/defs.h ++++ b/src/cmd/ksh93/include/defs.h +@@ -143,6 +143,7 @@ extern void sh_subjobcheck(pid_t); + extern int sh_subsavefd(int); + extern void sh_subtmpfile(void); + extern char *sh_substitute(const char*,const char*,char*); ++extern void sh_timetraps(void); + extern const char *_sh_translate(const char*); + extern int sh_trace(char*[],int); + extern void sh_trim(char*); +diff --git a/src/cmd/ksh93/include/fault.h b/src/cmd/ksh93/include/fault.h +index b57a0ab..7750f80 100644 +--- a/src/cmd/ksh93/include/fault.h ++++ b/src/cmd/ksh93/include/fault.h +@@ -58,6 +58,7 @@ typedef void (*SH_SIGTYPE)(int,void(*)(int)); + #define SH_SIGIGNORE 040 /* default is ignore signal */ + #define SH_SIGINTERACTIVE 0100 /* handle interactive specially */ + #define SH_SIGTSTP 0200 /* tstp signal received */ ++#define SH_SIGALRM 0200 /* timer alarm received */ + #define SH_SIGTERM SH_SIGOFF /* term signal received */ + #define SH_SIGRUNTIME 0400 /* runtime value */ + +diff --git a/src/cmd/ksh93/include/shell.h b/src/cmd/ksh93/include/shell.h +index 57c402d..9794995 100644 +--- a/src/cmd/ksh93/include/shell.h ++++ b/src/cmd/ksh93/include/shell.h +@@ -211,6 +211,7 @@ struct sh_scoped + char **otrap; /* save parent pseudosignals for v=$(trap) */ + char **trapcom; /* EXIT and signals */ + char **otrapcom; /* save parent EXIT and signals for v=$(trap) */ ++ void *timetrap; + struct Ufunction *real_fun; /* current 'function name' function */ + int repl_index; + char *repl_arg; +diff --git a/src/cmd/ksh93/sh/fault.c b/src/cmd/ksh93/sh/fault.c +index 3409a6c..510bf56 100644 +--- a/src/cmd/ksh93/sh/fault.c ++++ b/src/cmd/ksh93/sh/fault.c +@@ -447,6 +447,8 @@ void sh_chktrap(void) + sh_exit(sh.exitval); + } + } ++ if(sh.sigflag[SIGALRM]&SH_SIGALRM) ++ sh_timetraps(); + #if SHOPT_BGX + if((sh.sigflag[SIGCHLD]&SH_SIGTRAP) && sh.st.trapcom[SIGCHLD]) + job_chldtrap(1); +diff --git a/src/cmd/ksh93/sh/jobs.c b/src/cmd/ksh93/sh/jobs.c +index 116ae3b..be333b2 100644 +--- a/src/cmd/ksh93/sh/jobs.c ++++ b/src/cmd/ksh93/sh/jobs.c +@@ -1466,6 +1466,8 @@ int job_wait(pid_t pid) + continue; + if(nochild) + break; ++ if(sh.sigflag[SIGALRM]&SH_SIGTRAP) ++ sh_timetraps(); + if((intr && sh.trapnote) || (pid==1 && !intr)) + break; + } +diff --git a/src/cmd/ksh93/tests/builtins.sh b/src/cmd/ksh93/tests/builtins.sh +index 83b4086..92d2708 100755 +--- a/src/cmd/ksh93/tests/builtins.sh ++++ b/src/cmd/ksh93/tests/builtins.sh +@@ -1222,6 +1222,28 @@ function test_usage + done 3< <(builtin) + }; test_usage + ++# ====== ++# The 'alarm' builtin could make 'read' crash due to IFS table corruption caused by unsafe asynchronous execution. ++# https://bugzilla.redhat.com/1176670 ++if (builtin alarm) 2>/dev/null ++then got=$( { "$SHELL" -c ' ++ builtin alarm ++ alarm -r alarm_handler +.005 ++ i=0 ++ function alarm_handler.alarm ++ { ++ let "(++i) > 20" && exit ++ } ++ while :; do ++ echo cargo,odds and ends,jetsam,junk,wreckage,castoffs,sea-drift ++ done | while IFS="," read arg1 arg2 arg3 arg4 junk; do ++ : ++ done ++ '; } 2>&1) ++ ((!(e = $?))) || err_exit 'crash with alarm and IFS' \ ++ "(got status $e$( ((e>128)) && print -n /SIG && kill -l "$e"), $(printf %q "$got"))" ++fi ++ + # ====== + # Verify that the POSIX 'test' builtin exits with status 2 when given an invalid binary operator. + for operator in '===' ']]' +@@ -1581,7 +1603,7 @@ let Errors+=$? + # Most built-ins should handle --version + while IFS= read -r bltin <&3 + do case $bltin in +- echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) ++ alarm | echo | test | true | false | \[ | : | catclose | catgets | catopen | Dt* | _Dt* | X* | login | newgrp ) + continue ;; + fc | hist ) + ((SHOPT_SCRIPTONLY)) && continue ;; diff --git a/SOURCES/ksh-1.0.6-alarm-2.patch b/SOURCES/ksh-1.0.6-alarm-2.patch new file mode 100644 index 0000000..57d7ed1 --- /dev/null +++ b/SOURCES/ksh-1.0.6-alarm-2.patch @@ -0,0 +1,162 @@ +diff --git a/src/cmd/ksh93/Mamfile b/src/cmd/ksh93/Mamfile +index abc9ee1a5..d266f2178 100644 +--- a/src/cmd/ksh93/Mamfile ++++ b/src/cmd/ksh93/Mamfile +@@ -222,6 +222,10 @@ make install + prev shell.req + make alarm.o + make bltins/alarm.c ++ make include/io.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/sfio.h ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/io.h + make FEATURE/time implicit + prev features/time + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/time +@@ -239,6 +243,22 @@ make install + done FEATURE/dynamic generated + prev ${PACKAGE_ast_INCLUDE}/option.h + done include/builtins.h ++ make include/shlex.h implicit ++ make include/lexstates.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/wctype.h ++ prev ${PACKAGE_ast_INCLUDE}/wchar.h ++ make FEATURE/locale implicit ++ prev features/locale ++ exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale ++ done FEATURE/locale generated ++ done include/lexstates.h ++ prev include/shtable.h ++ make include/shnodes.h implicit ++ prev include/argnod.h implicit ++ prev ${PACKAGE_ast_INCLUDE}/ast.h ++ done include/shnodes.h ++ prev ${PACKAGE_ast_INCLUDE}/cdt.h ++ done include/shlex.h + prev ${PACKAGE_ast_INCLUDE}/error.h + make include/defs.h implicit + prev include/regress.h implicit +@@ -246,7 +266,7 @@ make install + prev include/shell.h + prev ${PACKAGE_ast_INCLUDE}/endian.h + prev include/name.h +- prev include/argnod.h implicit ++ prev include/argnod.h + prev ${PACKAGE_ast_INCLUDE}/cdt.h + prev FEATURE/externs + prev ${PACKAGE_ast_INCLUDE}/error.h +@@ -292,10 +312,7 @@ make install + make cflow.o + make bltins/cflow.c + prev include/builtins.h +- make include/shnodes.h implicit +- prev include/argnod.h +- prev ${PACKAGE_ast_INCLUDE}/ast.h +- done include/shnodes.h ++ prev include/shnodes.h + prev ${PACKAGE_ast_INCLUDE}/error.h + prev ${PACKAGE_ast_INCLUDE}/ast.h + prev include/defs.h +@@ -341,10 +358,7 @@ make install + done FEATURE/ttys generated + done include/terminal.h + prev ${PACKAGE_ast_INCLUDE}/sig.h +- make FEATURE/locale implicit +- prev features/locale +- exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/locale +- done FEATURE/locale generated ++ prev FEATURE/locale + make FEATURE/cmds implicit + prev features/cmds + exec - iffe ${IFFEFLAGS} -v -c "${CC} ${mam_cc_FLAGS} ${CCFLAGS} ${LDFLAGS}" ref ${mam_cc_L+-L.} ${mam_cc_L+-L${INSTALLROOT}/lib} -I${PACKAGE_ast_INCLUDE} -I${INSTALLROOT}/include ${mam_libdll} ${mam_libcmd} ${mam_libast} ${mam_libm} ${mam_libnsl} : run features/cmds +@@ -353,6 +367,7 @@ make install + prev include/builtins.h + prev include/history.h + prev include/name.h ++ prev include/io.h + make include/io.h implicit + prev ${PACKAGE_ast_INCLUDE}/sfio.h + prev ${PACKAGE_ast_INCLUDE}/ast.h +@@ -443,11 +458,7 @@ make install + prev include/builtins.h + prev include/name.h + prev include/io.h +- make include/lexstates.h implicit +- prev ${PACKAGE_ast_INCLUDE}/wctype.h +- prev ${PACKAGE_ast_INCLUDE}/wchar.h +- prev FEATURE/locale +- done include/lexstates.h ++ prev include/lexstates.h + prev include/variables.h + prev include/defs.h + prev ${PACKAGE_ast_INCLUDE}/error.h +@@ -545,12 +556,7 @@ make install + make whence.o + make bltins/whence.c + prev include/builtins.h +- make include/shlex.h implicit +- prev include/lexstates.h +- prev include/shtable.h +- prev include/shnodes.h +- prev ${PACKAGE_ast_INCLUDE}/cdt.h +- done include/shlex.h ++ prev include/shlex.h + prev include/path.h + prev include/name.h + prev include/shtable.h +diff --git a/src/cmd/ksh93/bltins/alarm.c b/src/cmd/ksh93/bltins/alarm.c +index f31bed711..63d4d6cbf 100644 +--- a/src/cmd/ksh93/bltins/alarm.c ++++ b/src/cmd/ksh93/bltins/alarm.c +@@ -23,21 +23,13 @@ + * + */ + +-/* +- * TODO: 2014 email from David Korn cited at : +- * +- * > I never documented the alarm builtin because it is problematic. The +- * > problem is that traps can't safely be handled asynchronously. What should +- * > happen is that the trap is marked for execution (sh.trapnote) and run after +- * > the current command completes. The time trap should wake up the shell if +- * > it is blocked and it should return and then handle the trap. +- */ +- + #include "shopt.h" + #include "defs.h" + #include ++#include + #include "builtins.h" + #include "FEATURE/time" ++#include "io.h" + + #define R_FLAG 1 + #define L_FLAG 2 +@@ -147,7 +139,26 @@ void sh_timetraps(void) + { + tp->flags &= ~L_FLAG; + if(tp->action) +- sh_fun(tp->action,tp->node,NULL); ++ { ++ /* Call the alarm discipline function. This may occur at any time including parse time, ++ * so save the lexer state and push/pop context to make sure we can restore it. */ ++ struct checkpt checkpoint; ++ int jmpval; ++ int savexit = sh.savexit; ++ Lex_t *lexp = (Lex_t*)sh.lex_context, savelex = *lexp; ++ sh_lexopen(lexp, 0); /* needs full init (0), not what it calls reinit (1) */ ++ sh_pushcontext(&checkpoint, 1); ++ jmpval = sigsetjmp(checkpoint.buff,0); ++ if(!jmpval) ++ sh_fun(tp->action,tp->node,NULL); ++ sh_popcontext(&checkpoint); ++ if(sh.topfd != checkpoint.topfd) ++ sh_iorestore(checkpoint.topfd,jmpval); ++ *lexp = savelex; ++ sh.savexit = savexit; /* avoid influencing $? */ ++ if(jmpval) ++ siglongjmp(*sh.jmplist,jmpval); ++ } + tp->flags &= ~L_FLAG; + if(!tp->flags) + nv_unset(tp->node); diff --git a/SOURCES/ksh-1.0.7-history-trim.patch b/SOURCES/ksh-1.0.7-history-trim.patch new file mode 100644 index 0000000..9b243e3 --- /dev/null +++ b/SOURCES/ksh-1.0.7-history-trim.patch @@ -0,0 +1,99 @@ +From 2075b2b96208ac8b989ca316dcdd674c3f488e2b Mon Sep 17 00:00:00 2001 +From: Martijn Dekker +Date: Thu, 28 Dec 2023 04:02:28 +0000 +Subject: [PATCH] Fix crash on failure to trim ~/.sh_history + +@vmihalko writes: +> We were able to reproduce an old issue mentioned in +> https://bugzilla.redhat.com/show_bug.cgi?id=1885399 using the +> latest version of ksh. The corresponding code has not changed +> much in the past few years. +> +> To provide further explanation, the problem arises when a user's +> .sh_history file grows to a size that triggers the hist_trim +> function, but the user lacks (after the creation of .sh_history) +> the necessary write permissions to their $HOME directory. As a +> result, ksh becomes stuck in a recursive loop between the +> sh_histinit(src/cmd/ksh93/edit/history.c#L203) function and the +> hist_trim(src/cmd/ksh93/edit/history.c#L417) function. +> +> Conditions for reproduction: +> +> 1. The size of the .sh_history file is larger than the HIST_MAX +> limit. (src/cmd/ksh93/edit/history.c, line 325) +> 2. .sh_history file has not been changed in the HIST_RECENT +> seconds (src/cmd/ksh93/edit/history.c, line 406) +> 3. The user does not have permission to write to the $HOME +> directory. + +src/cmd/ksh93/edit/history.c: hist_trim(): +- Print a warning and return if unlink(2) fails. The warning tells + the user to check the history file's parent directory is + writable. This is the best I realistically do for now, because + this function's basic method assumes a writable parent directory. +- The temp file fallback is deleted because it's fundamentally + flawed: it assumes the temp file is made on the same volume as + the history file and can simply be rename(2)'d in place. Even + on systems where this is the case, it doesn't appear to be + working correctly, but this is not worth looking into. + +Resolves: https://github.com/ksh93/ksh/issues/695 +--- + src/cmd/ksh93/edit/history.c | 34 ++++------------------------------ + 1 files changed, 4 insertions(+), 30 deletions(-) + +diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c +index c49c23244d00..f3672bf6e220 100644 +--- a/src/cmd/ksh93/edit/history.c ++++ b/src/cmd/ksh93/edit/history.c +@@ -419,34 +419,13 @@ static History_t* hist_trim(History_t *hp, int n) + char *cp; + int incmd=1, c=0; + History_t *hist_new, *hist_old = hp; +- char *buff, *endbuff, *tmpname=0; ++ char *buff, *endbuff; + off_t oldp,newp; + struct stat statb; +- unlink(hist_old->histname); +- if(access(hist_old->histname,F_OK) >= 0) ++ if(unlink(hist_old->histname) < 0) + { +- /* The unlink can fail on Windows 95 */ +- int fd; +- char *last, *name=hist_old->histname; +- sh_close(sffileno(hist_old->histfp)); +- tmpname = (char*)sh_malloc(strlen(name)+14); +- if(last = strrchr(name,'/')) +- { +- *last = 0; +- pathtmp(tmpname,name,"hist",NULL); +- *last = '/'; +- } +- else +- pathtmp(tmpname,e_dot,"hist",NULL); +- if(rename(name,tmpname) < 0) +- { +- free(tmpname); +- tmpname = name; +- } +- fd = open(tmpname,O_RDONLY|O_cloexec); +- sfsetfd(hist_old->histfp,fd); +- if(tmpname==name) +- tmpname = 0; ++ errormsg(SH_DICT,ERROR_warn(0),"cannot trim history file %s; make sure parent directory is writable",hist_old->histname); ++ return hist_ptr = hist_old; + } + hist_ptr = 0; + if(fstat(sffileno(hist_old->histfp),&statb)>=0) +@@ -501,11 +480,6 @@ static History_t* hist_trim(History_t *hp, int n) + } + hist_cancel(hist_new); + sfclose(hist_old->histfp); +- if(tmpname) +- { +- unlink(tmpname); +- free(tmpname); +- } + free((char*)hist_old); + return hist_ptr = hist_new; + } diff --git a/SOURCES/ksh-1.0.7-segfault-strdup.patch b/SOURCES/ksh-1.0.7-segfault-strdup.patch new file mode 100644 index 0000000..d52f539 --- /dev/null +++ b/SOURCES/ksh-1.0.7-segfault-strdup.patch @@ -0,0 +1,58 @@ +From 9eb8532ccacf1cfdb7ba18f51eba68776852ef7c Mon Sep 17 00:00:00 2001 +From: Vincent Mihalkovic +Date: Thu, 8 Feb 2024 22:10:58 +0100 +Subject: [PATCH] Re-fix use of strdup on a NULL pointer (re: 9a9da2c2) (#718) + +Thank you @lzaoral for debugging this issue and creating this +reproducer: + +$ tty # check that the shell is connected to a pseudoterminal +/dev/pts/4 +$ mkdir /var/tmp/chroottest +$ dnf --releasever=39 --installroot=/var/tmp/chroottest install ksh +$ echo "/dev/udp/127.0.0.1/514;0;104" | + sudo tee /var/tmp/chroottest/etc/ksh_audit +$ sudo chroot /var/tmp/chroottest /bin/ksh -lic 'exit 0' +(ksh segfaults) + +Analysis: On Linux, ttyname(3)[*] may fail if: + +* EBADF Bad file descriptor. +* ENODEV fd refers to a slave pseudoterminal device but the + corresponding pathname could not be found [...]. +* ENOTTY fd does not refer to a terminal device. + +Calling isatty(3) before ttyname(3) only prevents the first and +third cases. + +src/cmd/ksh93/edit/history.c: sh_histinit(): +- To catch the second case, let's call ttyname(2) directly, check + for NULL and remove the redundant isatty() call. + +[*] https://man7.org/linux/man-pages/man3/ttyname.3.html +--- + src/cmd/ksh93/edit/history.c | 4 +++- + 1 files changed, 3 insertions(+), 1 deletions(-) + +diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c +index a7b084e5c16f..25832a59265b 100644 +--- a/src/cmd/ksh93/edit/history.c ++++ b/src/cmd/ksh93/edit/history.c +@@ -15,6 +15,7 @@ + * Johnothan King * + * hyenias <58673227+hyenias@users.noreply.github.com> * + * Govind Kamat * ++* Vincent Mihalkovic * + * * + ***********************************************************************/ + /* +@@ -353,7 +354,8 @@ int sh_histinit(void) + if(fd>=0) + { + fcntl(fd,F_SETFD,FD_CLOEXEC); +- hp->tty = sh_strdup(isatty(2)?ttyname(2):"notty"); ++ const char* tty = ttyname(2); ++ hp->tty = sh_strdup(tty?tty:"notty"); + hp->auditfp = sfnew(NULL,NULL,-1,fd,SF_WRITE); + } + } diff --git a/SPECS/ksh.spec b/SPECS/ksh.spec index 27460c4..bad6c90 100644 --- a/SPECS/ksh.spec +++ b/SPECS/ksh.spec @@ -1,23 +1,30 @@ -%global verBetaPrefix 1.0.0 -%global verBetaSuffix 1 -%global verBetaFull %{verBetaPrefix}-beta.%{verBetaSuffix} - Name: ksh Summary: The Original ATT Korn Shell URL: http://www.kornshell.com/ License: EPL-1.0 Epoch: 3 -Version: %{verBetaPrefix}~beta.%{verBetaSuffix} +Version: 1.0.6 Release: 3%{?dist} -Source0: https://github.com/ksh93/%{name}/archive/v%{verBetaFull}/%{name}-%{verBetaFull}.tar.gz +Source0: https://github.com/ksh93/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz Source1: kshcomp.conf Source2: kshrc.rhs Source3: dotkshrc -# temporary commenting out failing tests -Patch1: %{name}-%{verBetaFull}-regre-tests.patch -# https://github.com/ksh93/ksh/commit/11177d448dadc7f8300e1db60c4ea5bdd61f13e0 -Patch2: %{name}-%{verBetaFull}-unset-PWD-segfault.patch +# The alarm builtin hase been temporarily removed from ksh in version 1.0.0. +# To prevent customer regressions we revert following upstream commits: +# https://github.com/ksh93/ksh/commit/4d50b69cbd5fce91d1f3c527dc170e192ceb4760 +# https://github.com/ksh93/ksh/commit/b369f40ded0ec7e8dd3d4a0e7226ccf037bb3400 +# https://github.com/ksh93/ksh/commit/3688842b7291db6fccdb44ff8e99ab8d4c1b2508 +Patch1: %{name}-1.0.6-alarm-1.patch +# alarm builtin was removed as it was unclear if it could ever be fixed +# alarm fixing patch from https://github.com/ksh93/ksh/issues/422#issuecomment-1581168550 +Patch2: %{name}-1.0.6-alarm-2.patch + +#https://github.com/ksh93/ksh/commit/2075b2b96208ac8b989ca316dcdd674c3f488e2b +Patch3: %{name}-1.0.7-history-trim.patch + +#upstream commit: https://github.com/ksh93/ksh/commit/9eb8532ccacf1cfdb7ba18f51eba68776852ef7c.patch +Patch4: ksh-1.0.7-segfault-strdup.patch Conflicts: pdksh Requires: coreutils, diffutils @@ -38,23 +45,20 @@ KornShell is a shell programming language, which is upward compatible with "sh" (the Bourne Shell). %prep -%autosetup -n %{name}-%{verBetaFull} -p1 +%autosetup -p1 #/dev/fd test does not work because of mock sed -i 's|ls /dev/fd|ls /proc/self/fd|' src/cmd/ksh93/features/options -# disable register for debugging -sed -i 1i"#define register" src/lib/libast/include/ast.h - %build -%set_build_flags XTRAFLAGS="" -for f in -Wno-unknown-pragmas -Wno-missing-braces -Wno-unused-result -Wno-return-type -Wno-int-to-pointer-cast -Wno-parentheses -Wno-unused -Wno-unused-but-set-variable -Wno-cpp -Wno-maybe-uninitialized -Wno-lto-type-mismatch -P +for f in -Wno-unknown-pragmas -Wno-missing-braces -Wno-unused-result -Wno-return-type -Wno-int-to-pointer-cast -Wno-parentheses -Wno-unused -Wno-unused-but-set-variable -Wno-cpp -Wno-maybe-uninitialized -Wno-lto-type-mismatch do $CC $f -E - /dev/null 2>&1 && XTRAFLAGS="$XTRAFLAGS $f" done -export CCFLAGS="$RPM_OPT_FLAGS $RPM_LD_FLAGS -fno-strict-aliasing $XTRAFLAGS" -./bin/package make -S +export CCFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing $XTRAFLAGS" +export LDFLAGS="$RPM_LD_FLAGS" +./bin/package make %install mkdir -p %{buildroot}{/bin,%{_bindir},%{_mandir}/man1} @@ -143,6 +147,19 @@ fi %config(noreplace) %{_sysconfdir}/binfmt.d/kshcomp.conf %changelog +* Sat Feb 10 2024 Vincent Mihalkovic - 3:1.0.6-3 +- Fix segfault in strdup + Resolves: RHEL-25019 + +* Wed Jan 03 2024 Vincent Mihalkovic - 3:1.0.6-2 +- Fix crash on failure to trim ~/.sh_history (#20345) + +* Mon Sep 18 2023 Vincent Mihalkovic - 3:1.0.6-1 +- Rebase to non-beta version, because upstream says it should to be used + https://github.com/ksh93/ksh/issues/667#issuecomment-1653665697 +- fix acl test case regression + Resolves: #2034188 + * Tue Jun 27 2023 Vincent Mihalkovic - 3:1.0.0~beta.1-3 - fix segfault when PWD is unset Resolves: #2123066