From 59d8a34f2dd5d5b27039c6a4ef055e977f2f5324 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Wed, 14 May 2025 19:33:18 +0000 Subject: [PATCH] import UBI zsh-5.9-15.el10 --- .gitignore | 2 +- .zsh.metadata | 1 - 0001-zsh-5.9-do-not-use-egrep-in-tests.patch | 178 +++ 0002-zsh-Use-int-main-in-test-c-codes.patch | 541 +++++++ ...dule-loading-problem-with-full-RELRO.patch | 69 + 0004-zsh-enable-PCRE-locale-switching.patch | 64 + 0005-zsh-port-to-pcre2.patch | 641 ++++++++ 0006-zsh-support-texinfo-7.0.patch | 53 + 0007-zsh-configure-c99.patch | 44 + 0008-zsh-deletefilelist-segfault.patch | 42 + ...h-5.5.1-CVE-2018-0502-CVE-2018-13259.patch | 148 -- SOURCES/0002-zsh-5.5.1-static-analysis.patch | 266 ---- ...03-zsh-5.5.1-parse-error-exit-status.patch | 28 - SOURCES/0004-zsh-5.5.1-CVE-2019-20044.patch | 1378 ----------------- SOURCES/0005-zsh-5.5.1-CVE-2021-45444.patch | 45 - SOURCES/0006-zsh-5.5.1-fix-wait.patch | 28 - dotzprofile | 12 + SOURCES/dotzshrc => dotzshrc | 0 sources | 1 + SOURCES/zlogin.rhs => zlogin.rhs | 0 SOURCES/zlogout.rhs => zlogout.rhs | 0 SOURCES/zprofile.rhs => zprofile.rhs | 3 - SPECS/zsh.spec => zsh.spec | 201 ++- SOURCES/zshenv.rhs => zshenv.rhs | 0 SOURCES/zshrc.rhs => zshrc.rhs | 2 +- 25 files changed, 1787 insertions(+), 1960 deletions(-) delete mode 100644 .zsh.metadata create mode 100644 0001-zsh-5.9-do-not-use-egrep-in-tests.patch create mode 100644 0002-zsh-Use-int-main-in-test-c-codes.patch create mode 100644 0003-zsh-fix-module-loading-problem-with-full-RELRO.patch create mode 100644 0004-zsh-enable-PCRE-locale-switching.patch create mode 100644 0005-zsh-port-to-pcre2.patch create mode 100644 0006-zsh-support-texinfo-7.0.patch create mode 100644 0007-zsh-configure-c99.patch create mode 100644 0008-zsh-deletefilelist-segfault.patch delete mode 100644 SOURCES/0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch delete mode 100644 SOURCES/0002-zsh-5.5.1-static-analysis.patch delete mode 100644 SOURCES/0003-zsh-5.5.1-parse-error-exit-status.patch delete mode 100644 SOURCES/0004-zsh-5.5.1-CVE-2019-20044.patch delete mode 100644 SOURCES/0005-zsh-5.5.1-CVE-2021-45444.patch delete mode 100644 SOURCES/0006-zsh-5.5.1-fix-wait.patch create mode 100644 dotzprofile rename SOURCES/dotzshrc => dotzshrc (100%) create mode 100644 sources rename SOURCES/zlogin.rhs => zlogin.rhs (100%) rename SOURCES/zlogout.rhs => zlogout.rhs (100%) rename SOURCES/zprofile.rhs => zprofile.rhs (90%) rename SPECS/zsh.spec => zsh.spec (71%) rename SOURCES/zshenv.rhs => zshenv.rhs (100%) rename SOURCES/zshrc.rhs => zshrc.rhs (93%) diff --git a/.gitignore b/.gitignore index 08493c2..e21a20d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/zsh-5.5.1.tar.xz +zsh-5.9.tar.xz diff --git a/.zsh.metadata b/.zsh.metadata deleted file mode 100644 index 4899962..0000000 --- a/.zsh.metadata +++ /dev/null @@ -1 +0,0 @@ -98ea952bba9b8752635c75f54bcecef072d3036e SOURCES/zsh-5.5.1.tar.xz diff --git a/0001-zsh-5.9-do-not-use-egrep-in-tests.patch b/0001-zsh-5.9-do-not-use-egrep-in-tests.patch new file mode 100644 index 0000000..4d5a1cf --- /dev/null +++ b/0001-zsh-5.9-do-not-use-egrep-in-tests.patch @@ -0,0 +1,178 @@ +From 6935aa4b515fe9b782507820c77ab681136470bc Mon Sep 17 00:00:00 2001 +From: Jun-ichi Takimoto +Date: Thu, 15 Sep 2022 18:56:20 +0900 +Subject: [PATCH] 50629: do not use egrep in tests + +Upstream-commit: 4fc5dc0292acd77f17281f451774ba2ca4203026 +Signed-off-by: Kamil Dudka +--- + Test/D07multibyte.ztst | 16 ++-------------- + Test/E01options.ztst | 2 +- + Test/V07pcre.ztst | 16 ++-------------- + Test/X02zlevi.ztst | 11 +---------- + Test/X03zlebindkey.ztst | 11 +---------- + Test/Y01completion.ztst | 11 +---------- + Test/ztst.zsh | 15 +++++++++++++++ + 7 files changed, 23 insertions(+), 59 deletions(-) + +diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst +index e2e9a25..6909346 100644 +--- a/Test/D07multibyte.ztst ++++ b/Test/D07multibyte.ztst +@@ -1,19 +1,7 @@ + %prep + +-# Find a UTF-8 locale. +- setopt multibyte +-# Don't let LC_* override our choice of locale. +- unset -m LC_\* +- mb_ok= +- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 +- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) +- for LANG in $langs; do +- if [[ é = ? ]]; then +- mb_ok=1 +- break; +- fi +- done +- if [[ -z $mb_ok ]]; then ++ LANG=$(ZTST_find_UTF8) ++ if [[ -z $LANG ]]; then + ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented" + else + print -u $ZTST_fd Testing multibyte with locale $LANG +diff --git a/Test/E01options.ztst b/Test/E01options.ztst +index 2acbfd3..d38fbed 100644 +--- a/Test/E01options.ztst ++++ b/Test/E01options.ztst +@@ -651,7 +651,7 @@ + >noktarg1 + >0 1 + +- showopt() { setopt | egrep 'localoptions|ksharrays'; } ++ showopt() { echo ${(FM)${(@f)"$(setopt)"}:#(localoptions|ksharrays)*} } + f1() { setopt localoptions ksharrays; showopt } + f2() { setopt ksharrays; showopt } + setopt kshoptionprint +diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst +index c9c844d..ca13419 100644 +--- a/Test/V07pcre.ztst ++++ b/Test/V07pcre.ztst +@@ -6,20 +6,8 @@ + return 0 + fi + setopt rematch_pcre +-# Find a UTF-8 locale. +- setopt multibyte +-# Don't let LC_* override our choice of locale. +- unset -m LC_\* +- mb_ok= +- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 +- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) +- for LANG in $langs; do +- if [[ é = ? ]]; then +- mb_ok=1 +- break; +- fi +- done +- if [[ -z $mb_ok ]]; then ++ LANG=$(ZTST_find_UTF8) ++ if [[ -z $LANG ]]; then + ZTST_unimplemented="no UTF-8 locale or multibyte mode is not implemented" + else + print -u $ZTST_fd Testing PCRE multibyte with locale $LANG +diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst +index 8146d67..203c13c 100644 +--- a/Test/X02zlevi.ztst ++++ b/Test/X02zlevi.ztst +@@ -1,16 +1,7 @@ + # Tests of the vi mode of ZLE + + %prep +- unset -m LC_\* +- ZSH_TEST_LANG= +- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 +- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) +- for LANG in $langs; do +- if [[ é = ? ]]; then +- ZSH_TEST_LANG=$LANG +- break; +- fi +- done ++ ZSH_TEST_LANG=$(ZTST_find_UTF8) + if ( zmodload zsh/zpty 2>/dev/null ); then + . $ZTST_srcdir/comptest + comptestinit -v -z $ZTST_testdir/../Src/zsh +diff --git a/Test/X03zlebindkey.ztst b/Test/X03zlebindkey.ztst +index 43692a8..5277332 100644 +--- a/Test/X03zlebindkey.ztst ++++ b/Test/X03zlebindkey.ztst +@@ -3,16 +3,7 @@ + # into bindings. The latter is particularly tricky with multibyte sequences. + + %prep +- unset -m LC_\* +- ZSH_TEST_LANG= +- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 +- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) +- for LANG in $langs; do +- if [[ é = ? ]]; then +- ZSH_TEST_LANG=$LANG +- break; +- fi +- done ++ ZSH_TEST_LANG=$(ZTST_find_UTF8) + if ( zmodload zsh/zpty 2>/dev/null ); then + . $ZTST_srcdir/comptest + comptestinit -z $ZTST_testdir/../Src/zsh +diff --git a/Test/Y01completion.ztst b/Test/Y01completion.ztst +index 6af0efc..f976f9f 100644 +--- a/Test/Y01completion.ztst ++++ b/Test/Y01completion.ztst +@@ -1,16 +1,7 @@ + # Tests for completion system. + + %prep +- unset -m LC_\* +- ZSH_TEST_LANG= +- langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 +- $(locale -a 2>/dev/null | egrep 'utf8|UTF-8')) +- for LANG in $langs; do +- if [[ é = ? ]]; then +- ZSH_TEST_LANG=$LANG +- break; +- fi +- done ++ ZSH_TEST_LANG=$(ZTST_find_UTF8) + if ( zmodload zsh/zpty 2>/dev/null ); then + . $ZTST_srcdir/comptest + mkdir comp.tmp +diff --git a/Test/ztst.zsh b/Test/ztst.zsh +index aca275c..d95b726 100755 +--- a/Test/ztst.zsh ++++ b/Test/ztst.zsh +@@ -37,6 +37,21 @@ emulate -R zsh + # LANG must be passed to child zsh. + export LANG + ++# find UTF-8 locale ++ZTST_find_UTF8 () { ++ setopt multibyte ++ # Don't let LC_* override our choice of locale. ++ unset -m LC_\* ++ local langs=(en_{US,GB}.{UTF-,utf}8 en.UTF-8 ++ ${(M)$(locale -a 2>/dev/null):#*.(utf8|UTF-8)}) ++ for LANG in $langs; do ++ if [[ é = ? ]]; then ++ echo $LANG ++ return ++ fi ++ done ++} ++ + # Don't propagate variables that are set by default in the shell. + typeset +x WORDCHARS + +-- +2.39.0 + diff --git a/0002-zsh-Use-int-main-in-test-c-codes.patch b/0002-zsh-Use-int-main-in-test-c-codes.patch new file mode 100644 index 0000000..3585cc4 --- /dev/null +++ b/0002-zsh-Use-int-main-in-test-c-codes.patch @@ -0,0 +1,541 @@ +commit ab4d62eb975a4c4c51dd35822665050e2ddc6918 +Author: Nicholas Vinson +Date: Wed Sep 21 09:22:11 2022 +0900 + + 50641: use 'int main()' in test C-codes in configure + +diff --git a/aczsh.m4 b/aczsh.m4 +index 1209ac614..b31236020 100644 +--- a/aczsh.m4 ++++ b/aczsh.m4 +@@ -44,6 +44,7 @@ AC_DEFUN(zsh_64_BIT_TYPE, + #include + #endif + ++int + main() + { + $1 foo = 0; +@@ -118,7 +119,6 @@ AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS + AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AS_MESSAGE_LOG_FD) && + AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AS_MESSAGE_LOG_FD); then + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -146,29 +146,30 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + ++int + main() + { + void *handle1, *handle2; + void *(*zsh_getaddr1)(), *(*zsh_getaddr2)(); + void *sym1, *sym2; + handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle1) exit(1); ++ if(!handle1) return(1); + handle2 = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle2) exit(1); ++ if(!handle2) return(1); + zsh_getaddr1 = (void *(*)()) dlsym(handle1, "${us}zsh_getaddr1"); + zsh_getaddr2 = (void *(*)()) dlsym(handle2, "${us}zsh_getaddr2"); + sym1 = zsh_getaddr1(); + sym2 = zsh_getaddr2(); +- if(!sym1 || !sym2) exit(1); +- if(sym1 != sym2) exit(1); ++ if(!sym1 || !sym2) return(1); ++ if(sym1 != sym2) return(1); + dlclose(handle1); + handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle1) exit(1); ++ if(!handle1) return(1); + zsh_getaddr1 = (void *(*)()) dlsym(handle1, "${us}zsh_getaddr1"); + sym1 = zsh_getaddr1(); +- if(!sym1) exit(1); +- if(sym1 != sym2) exit(1); +- exit(0); ++ if(!sym1) return(1); ++ if(sym1 != sym2) return(1); ++ return(0); + } + ]])],[zsh_cv_shared_$1=yes], + [zsh_cv_shared_$1=no], +@@ -200,7 +201,6 @@ AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS + AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AS_MESSAGE_LOG_FD) && + AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AS_MESSAGE_LOG_FD); then + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -228,19 +228,19 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + +- ++int + main() + { + void *handle1, *handle2; + int (*fred1)(), (*fred2)(); + handle1 = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle1) exit(1); ++ if(!handle1) return(1); + handle2 = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle2) exit(1); ++ if(!handle2) return(1); + fred1 = (int (*)()) dlsym(handle1, "${us}fred"); + fred2 = (int (*)()) dlsym(handle2, "${us}fred"); +- if(!fred1 || !fred2) exit(1); +- exit((*fred1)() != 42 || (*fred2)() != 69); ++ if(!fred1 || !fred2) return(1); ++ return((*fred1)() != 42 || (*fred2)() != 69); + } + ]])],[zsh_cv_sys_dynamic_clash_ok=yes], + [zsh_cv_sys_dynamic_clash_ok=no], +@@ -276,7 +276,6 @@ AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS + AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest2.c 1>&AS_MESSAGE_LOG_FD) && + AC_TRY_COMMAND($DLLD -o conftest2.$DL_EXT $LDFLAGS $DLLDFLAGS conftest2.o $LIBS 1>&AS_MESSAGE_LOG_FD); then + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -304,17 +303,18 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + ++int + main() + { + void *handle; + int (*barneysym)(); + handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle) exit(1); ++ if(!handle) return(1); + handle = dlopen("./conftest2.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle) exit(1); ++ if(!handle) return(1); + barneysym = (int (*)()) dlsym(handle, "${us}barney"); +- if(!barneysym) exit(1); +- exit((*barneysym)() != 69); ++ if(!barneysym) return(1); ++ return((*barneysym)() != 69); + } + ]])],[zsh_cv_sys_dynamic_rtld_global=yes], + [zsh_cv_sys_dynamic_rtld_global=no], +@@ -346,7 +346,6 @@ AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS conftest1.o $LIBS + save_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS" + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -374,15 +373,16 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + ++int + main() + { + void *handle; + int (*barneysym)(); + handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle) exit(1); ++ if(!handle) return(1); + barneysym = (int (*)()) dlsym(handle, "${us}barney"); +- if(!barneysym) exit(1); +- exit((*barneysym)() != 69); ++ if(!barneysym) return(1); ++ return((*barneysym)() != 69); + } + + int fred () { return 42; } +@@ -420,7 +420,6 @@ elif + save_ldflags=$LDFLAGS + LDFLAGS="$LDFLAGS $EXTRA_LDFLAGS -s" + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -448,15 +447,16 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + ++int + main() + { + void *handle; + int (*barneysym)(); + handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle) exit(1); ++ if(!handle) return(1); + barneysym = (int (*)()) dlsym(handle, "${us}barney"); +- if(!barneysym) exit(1); +- exit((*barneysym)() != 69); ++ if(!barneysym) return(1); ++ return((*barneysym)() != 69); + } + + int fred () { return 42; } +@@ -488,7 +488,6 @@ echo 'int fred () { return 42; }' > conftest1.c + if AC_TRY_COMMAND($CC -c $CFLAGS $CPPFLAGS $DLCFLAGS conftest1.c 1>&AS_MESSAGE_LOG_FD) && + AC_TRY_COMMAND($DLLD -o conftest1.$DL_EXT $LDFLAGS $DLLDFLAGS -s conftest1.o $LIBS 1>&AS_MESSAGE_LOG_FD); then + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -516,15 +515,16 @@ char *zsh_gl_sym_addr ; + #define RTLD_GLOBAL 0 + #endif + ++int + main() + { + void *handle; + int (*fredsym)(); + handle = dlopen("./conftest1.$DL_EXT", RTLD_LAZY | RTLD_GLOBAL); +- if(!handle) exit(1); ++ if(!handle) return(1); + fredsym = (int (*)()) dlsym(handle, "${us}fred"); +- if(!fredsym) exit(1); +- exit((*fredsym)() != 42); ++ if(!fredsym) return(1); ++ return((*fredsym)() != 42); + } + ]])],[zsh_cv_sys_dynamic_strip_lib=yes], + [zsh_cv_sys_dynamic_strip_lib=no], +diff --git a/configure.ac b/configure.ac +index 890ef8dd2..074141d38 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -585,7 +585,7 @@ fi + dnl Checking if compiler correctly cast signed to unsigned. + AC_CACHE_CHECK(if signed to unsigned casting is broken, + zsh_cv_c_broken_signed_to_unsigned_casting, +-[AC_RUN_IFELSE([AC_LANG_SOURCE([[main(){return((int)(unsigned char)((char) -1) == 255);}]])],[zsh_cv_c_broken_signed_to_unsigned_casting=yes],[zsh_cv_c_broken_signed_to_unsigned_casting=no],[zsh_cv_c_broken_signed_to_unsigned_casting=no])]) ++[AC_RUN_IFELSE([AC_LANG_SOURCE([[int main(){return((int)(unsigned char)((char) -1) == 255);}]])],[zsh_cv_c_broken_signed_to_unsigned_casting=yes],[zsh_cv_c_broken_signed_to_unsigned_casting=no],[zsh_cv_c_broken_signed_to_unsigned_casting=no])]) + AH_TEMPLATE([BROKEN_SIGNED_TO_UNSIGNED_CASTING], + [Define to 1 if compiler incorrectly cast signed to unsigned.]) + if test x$zsh_cv_c_broken_signed_to_unsigned_casting = xyes; then +@@ -1046,7 +1046,7 @@ else + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + +-main() { return sizeof(off_t) < 8; } ++int main() { return sizeof(off_t) < 8; } + ]])],[zsh_cv_off_t_is_64_bit=yes],[zsh_cv_off_t_is_64_bit=no],[zsh_cv_off_t_is_64_bit=no])]) + if test x$zsh_cv_off_t_is_64_bit = xyes; then + AC_DEFINE(OFF_T_IS_64_BIT) +@@ -1056,7 +1056,7 @@ main() { return sizeof(off_t) < 8; } + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + +-main() { return sizeof(ino_t) < 8; } ++int main() { return sizeof(ino_t) < 8; } + ]])],[zsh_cv_ino_t_is_64_bit=yes],[zsh_cv_ino_t_is_64_bit=no],[zsh_cv_ino_t_is_64_bit=no])]) + if test x$zsh_cv_ino_t_is_64_bit = xyes; then + AC_DEFINE(INO_T_IS_64_BIT) +@@ -1369,7 +1369,7 @@ zsh_cv_func_realpath_accepts_null, + #include + #include + ],[ +-exit(!realpath("/", (char*)0)); ++return(!realpath("/", (char*)0)); + ])], + [zsh_cv_func_realpath_accepts_null=yes], + [zsh_cv_func_realpath_accepts_null=no], +@@ -1393,10 +1393,9 @@ AC_CACHE_CHECK(if tgetent accepts NULL, + zsh_cv_func_tgetent_accepts_null, + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include +-#include + int tgetent(char *, char *); + char *tgetstr(char *, char **); +-main() ++int main() + { + char buf[4096]; + int r1 = tgetent(buf, "vt100"); +@@ -1407,7 +1406,7 @@ main() + tgetstr("cl", &u); + creat("conftest.tgetent", 0640); + } +- exit((r1 != r2) || r2 == -1); ++ return((r1 != r2) || r2 == -1); + } + ]])],[if test -f conftest.tgetent; then + zsh_cv_func_tgetent_accepts_null=yes +@@ -1421,10 +1420,9 @@ AC_CACHE_CHECK(if tgetent returns 0 on success, + zsh_cv_func_tgetent_zero_success, + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include +-#include + int tgetent(char *, char*); + char *tgetstr(char *, char **); +-main() ++int main() + { + char buf[4096]; + int r1 = tgetent(buf, "!@#$%^&*"); +@@ -1435,7 +1433,7 @@ main() + tgetstr("cl", &u); + creat("conftest.tgetent0", 0640); + } +- exit(r1 == r2); ++ return(r1 == r2); + } + ]])],[if test -f conftest.tgetent0; then + zsh_cv_func_tgetent_zero_success=yes +@@ -1869,8 +1867,7 @@ zsh_cv_rlim_t_is_longer, + #include + #endif + #include +-#include +-main(){struct rlimit r;exit(sizeof(r.rlim_cur) <= sizeof(long));}]])],[zsh_cv_rlim_t_is_longer=yes],[zsh_cv_rlim_t_is_longer=no],[zsh_cv_rlim_t_is_longer=yes])]) ++int main(){struct rlimit r;return(sizeof(r.rlim_cur) <= sizeof(long));}]])],[zsh_cv_rlim_t_is_longer=yes],[zsh_cv_rlim_t_is_longer=no],[zsh_cv_rlim_t_is_longer=yes])]) + if test x$zsh_cv_rlim_t_is_longer = xyes; then + AC_CACHE_CHECK(if rlim_t is a quad, + zsh_cv_rlim_t_is_quad_t, +@@ -1880,13 +1877,12 @@ if test x$zsh_cv_rlim_t_is_longer = xyes; then + #endif + #include + #include +-#include +-main() { ++int main() { + struct rlimit r; + char buf[20]; + r.rlim_cur = 0; + sprintf(buf, "%qd", r.rlim_cur); +- exit(strcmp(buf, "0")); ++ return(strcmp(buf, "0")); + }]])],[zsh_cv_rlim_t_is_quad_t=yes],[zsh_cv_rlim_t_is_quad_t=no],[zsh_cv_rlim_t_is_quad_t=no])]) + if test x$zsh_cv_rlim_t_is_quad_t = xyes; then + AC_DEFINE(RLIM_T_IS_QUAD_T) +@@ -1903,8 +1899,7 @@ else + #include + #endif + #include +-#include +- main(){struct rlimit r;r.rlim_cur=-1;exit(r.rlim_cur<0);}]])],[zsh_cv_type_rlim_t_is_unsigned=yes],[zsh_cv_type_rlim_t_is_unsigned=no],[zsh_cv_type_rlim_t_is_unsigned=no])]) ++ int main(){struct rlimit r;r.rlim_cur=-1;return(r.rlim_cur<0);}]])],[zsh_cv_type_rlim_t_is_unsigned=yes],[zsh_cv_type_rlim_t_is_unsigned=no],[zsh_cv_type_rlim_t_is_unsigned=no])]) + if test x$zsh_cv_type_rlim_t_is_unsigned = xyes; then + AC_DEFINE(RLIM_T_IS_UNSIGNED) + DEFAULT_RLIM_T="unsigned $DEFAULT_RLIM_T" +@@ -2187,9 +2182,8 @@ zsh_cv_sys_fifo, + #include + #include + #include +-#include + #include +-main() ++int main() + { + char c; + int fd; +@@ -2200,18 +2194,18 @@ main() + #else + if(mknod("/tmp/fifo$$", 0010600, 0) < 0) + #endif +- exit(1); ++ return(1); + pid = fork(); + if(pid < 0) +- exit(1); ++ return(1); + if(pid) { + fd = open("/tmp/fifo$$", O_RDONLY); +- exit(fd < 0 || read(fd, &c, 1) != 1 || c != 'x'); ++ return(fd < 0 || read(fd, &c, 1) != 1 || c != 'x'); + } + fd = open("/tmp/fifo$$", O_WRONLY); + ret = (fd < 0 || write(fd, "x", 1) < 1); + unlink("/tmp/fifo$$"); +- exit(ret); ++ return(ret); + } + ]])],[zsh_cv_sys_fifo=yes],[zsh_cv_sys_fifo=no],[zsh_cv_sys_fifo=yes]) + ]) +@@ -2289,8 +2283,7 @@ zsh_cv_sys_link, + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + #include +-#include +-main() ++int main() + { + int ret; + char *tmpfile, *newfile; +@@ -2299,11 +2292,11 @@ main() + unlink(tmpfile); + unlink(newfile); + if(creat(tmpfile, 0644) < 0) +- exit(1); ++ return(1); + ret = link(tmpfile, newfile); + unlink(tmpfile); + unlink(newfile); +- exit(ret<0); ++ return(ret<0); + } + ]])],[zsh_cv_sys_link=yes],[zsh_cv_sys_link=no],[zsh_cv_sys_link=yes])]) + AH_TEMPLATE([HAVE_LINK], +@@ -2322,12 +2315,11 @@ zsh_cv_sys_killesrch, + #include + #include + #include +-#include +-main() ++int main() + { + int pid = (getpid() + 10000) & 0xffffff; + while (pid && (kill(pid, 0) == 0 || errno != ESRCH)) pid >>= 1; +- exit(errno!=ESRCH); ++ return(errno!=ESRCH); + } + ]])],[zsh_cv_sys_killesrch=yes],[zsh_cv_sys_killesrch=no],[zsh_cv_sys_killesrch=yes])]) + AH_TEMPLATE([BROKEN_KILL_ESRCH], +@@ -2348,12 +2340,11 @@ if test x$signals_style = xPOSIX_SIGNALS; then + [AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include + #include +-#include + int child=0; + void handler(sig) + int sig; + {if(sig==SIGCHLD) child=1;} +-main() { ++int main() { + struct sigaction act; + sigset_t set; + int pid, ret; +@@ -2368,7 +2359,7 @@ main() { + if(pid>0) { + sigemptyset(&set); + ret=sigsuspend(&set); +- exit(child==0); ++ return(child==0); + } + } + ]])],[zsh_cv_sys_sigsuspend=yes],[zsh_cv_sys_sigsuspend=no],[zsh_cv_sys_sigsuspend=yes])]) +@@ -2400,15 +2391,14 @@ case "x$zsh_working_tcsetpgrp" in + #include + #include + #include +-#include +-main() { ++int main() { + int fd; + int ret; + fd=open("/dev/tty", O_RDWR); +- if (fd < 0) exit(2); ++ if (fd < 0) return(2); + ret=tcsetpgrp(fd, tcgetpgrp(fd)); +- if (ret < 0) exit(1); +- exit(0); ++ if (ret < 0) return(1); ++ return(0); + } + ]])],[zsh_cv_sys_tcsetpgrp=yes],[ + case $? in +@@ -2448,7 +2438,7 @@ if test x$ac_cv_func_getpwnam = xyes; then + #include + #include + #include +-main() { ++int main() { + struct passwd *pw1, *pw2; + char buf[1024], name[1024]; + sprintf(buf, "%d:%d", getpid(), rand()); +@@ -2456,7 +2446,7 @@ main() { + if (pw1) strcpy(name, pw1->pw_name); + sprintf(buf, "%d:%d", rand(), getpid()); + pw2=getpwnam(buf); +- exit(pw1!=0 && pw2!=0 && !strcmp(name, pw2->pw_name)); ++ return(pw1!=0 && pw2!=0 && !strcmp(name, pw2->pw_name)); + } + ]])],[zsh_cv_sys_getpwnam_faked=no],[zsh_cv_sys_getpwnam_faked=yes],[zsh_cv_sys_getpwnam_faked=no])]) + if test x$zsh_cv_sys_getpwnam_faked = xyes; then +@@ -2775,20 +2765,17 @@ elif test "x$dynamic" = xyes; then + zsh_cv_sys_elf, + [AC_RUN_IFELSE([AC_LANG_SOURCE([[/* Test for whether ELF binaries are produced */ + #include +-#include + #include +-main(argc, argv) +-int argc; +-char *argv[]; ++int main(int argc, char *argv[]) + { + char b[4]; + int i = open(argv[0],O_RDONLY); + if(i == -1) +- exit(1); /* fail */ ++ return(1); /* fail */ + if(read(i,b,4)==4 && b[0]==127 && b[1]=='E' && b[2]=='L' && b[3]=='F') +- exit(0); /* succeed (yes, it's ELF) */ ++ return(0); /* succeed (yes, it's ELF) */ + else +- exit(1); /* fail */ ++ return(1); /* fail */ + }]])],[zsh_cv_sys_elf=yes],[zsh_cv_sys_elf=no],[zsh_cv_sys_elf=yes])]) + + # We use [0-9]* in case statements, so need to change quoting +@@ -2924,13 +2911,12 @@ LDFLAGS="$old_LDFLAGS") + AC_CACHE_CHECK(if your dlsym() needs a leading underscore, + zsh_cv_func_dlsym_needs_underscore, + [echo failed >conftestval && cat >conftest.c <&AS_MESSAGE_LOG_FD) && + AC_TRY_COMMAND($DLLD $LDFLAGS $DLLDFLAGS -o conftest.$DL_EXT conftest.o 1>&AS_MESSAGE_LOG_FD) && + AC_RUN_IFELSE([AC_LANG_SOURCE([[ + #include +-#include + #ifdef HPUX10DYNAMIC + #include + #define RTLD_LAZY BIND_DEFERRED +@@ -2957,16 +2943,16 @@ char *zsh_gl_sym_addr ; + + extern int fred() ; + +-main() ++int main() + { + void * handle ; + void * symbol ; + FILE *f=fopen("conftestval", "w"); +- if (!f) exit(1); ++ if (!f) return(1); + handle = dlopen("./conftest.$DL_EXT", RTLD_LAZY) ; + if (handle == NULL) { + fprintf (f, "dlopen failed") ; +- exit(1); ++ return(1); + } + symbol = dlsym(handle, "fred") ; + if (symbol == NULL) { +@@ -2974,13 +2960,13 @@ main() + symbol = dlsym(handle, "_fred") ; + if (symbol == NULL) { + fprintf (f, "dlsym failed") ; +- exit(1); ++ return(1); + } + fprintf (f, "yes") ; + } + else + fprintf (f, "no") ; +- exit(0); ++ return(0); + }]])],[zsh_cv_func_dlsym_needs_underscore=`cat conftestval`],[zsh_cv_func_dlsym_needs_underscore=failed + dynamic=no],[zsh_cv_func_dlsym_needs_underscore=no])]) + if test "x$zsh_cv_func_dlsym_needs_underscore" = xyes; then diff --git a/0003-zsh-fix-module-loading-problem-with-full-RELRO.patch b/0003-zsh-fix-module-loading-problem-with-full-RELRO.patch new file mode 100644 index 0000000..2ca953b --- /dev/null +++ b/0003-zsh-fix-module-loading-problem-with-full-RELRO.patch @@ -0,0 +1,69 @@ +From a84fdd7c8f77935ecce99ff2b0bdba738821ed79 Mon Sep 17 00:00:00 2001 +From: Jun-ichi Takimoto +Date: Mon, 26 Jun 2023 17:13:04 +0900 +Subject: [PATCH] 51889: fix module loading problem with full RELRO + +If full RELRO (relocation read-only, one of the security enhancement +methods for ELF-based systems) is used when building zsh (as in binary +packages of most Linuxes), loading a module (e.g. zsh/zftp) fails unless +all the modules it depends on are already loaded. With this patch the +necessary modules are automatically loaded. + +Upstream-commit: a84fdd7c8f77935ecce99ff2b0bdba738821ed79 +Signed-off-by: Lukáš Zaoral +--- + Src/Modules/zftp.c | 2 +- + Src/mkbltnmlst.sh | 24 ++++++++++++++++++++++++ + 2 files changed, 25 insertions(+), 1 deletion(-) + +diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c +index 49b3ffa89..47a5e9de9 100644 +--- a/Src/Modules/zftp.c ++++ b/Src/Modules/zftp.c +@@ -3172,7 +3172,7 @@ static struct features module_features = { + int + setup_(UNUSED(Module m)) + { +- return (require_module("zsh/net/tcp", NULL, 0) == 1); ++ return 0; + } + + /**/ +diff --git a/Src/mkbltnmlst.sh b/Src/mkbltnmlst.sh +index c4611d8b3..067ecdaf9 100644 +--- a/Src/mkbltnmlst.sh ++++ b/Src/mkbltnmlst.sh +@@ -76,6 +76,30 @@ for x_mod in $x_mods; do + test "x$linked" = xno && echo "#endif" + done + ++# if dynamic module 'mod' with load=no has moddeps in its .mdd, ++# then output add_dep(mod, dep) for each 'dep' in moddeps. ++dyn_mods="`grep ' link=dynamic .* load=no ' $CFMOD | \ ++ sed -e '/^#/d' -e 's/ .*/ /' -e 's/^name=/ /'`" ++ ++for mod in $dyn_mods; do ++ modfile="`grep '^name='$mod' ' $CFMOD | \ ++ sed -e 's/^.* modfile=//' -e 's/ .*//'`" ++ if test "x$modfile" = x; then ++ echo >&2 "WARNING: no name for \`$mod' in $CFMOD (ignored)" ++ continue ++ fi ++ unset moddeps ++ . $srcdir/../$modfile ++ if test -n "$moddeps"; then ++ echo '#ifdef DYNAMIC' ++ echo "/* non-linked-in known module \`$mod' */" ++ for dep in $moddeps; do ++ echo " add_dep(\"$mod\", \"$dep\");" ++ done ++ echo '#endif' ++ fi ++done ++ + echo + done_mods=" " + for bin_mod in $bin_mods; do +-- +2.41.0 + diff --git a/0004-zsh-enable-PCRE-locale-switching.patch b/0004-zsh-enable-PCRE-locale-switching.patch new file mode 100644 index 0000000..a6f03bf --- /dev/null +++ b/0004-zsh-enable-PCRE-locale-switching.patch @@ -0,0 +1,64 @@ +From 1b421e4978440234fb73117c8505dad1ccc68d46 Mon Sep 17 00:00:00 2001 +From: Jun-ichi Takimoto +Date: Mon, 26 Sep 2022 10:52:50 +0900 +Subject: [PATCH] 50658 + test: Enable to switch between C/UTF-8 locales in + PCRE + +--- + Src/Modules/pcre.c | 10 ++-------- + Test/V07pcre.ztst | 11 +++++++++++ + 2 files changed, 13 insertions(+), 8 deletions(-) + +diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c +index 6289e003e..46875a59b 100644 +--- a/Src/Modules/pcre.c ++++ b/Src/Modules/pcre.c +@@ -47,8 +47,6 @@ zpcre_utf8_enabled(void) + #if defined(MULTIBYTE_SUPPORT) && defined(HAVE_NL_LANGINFO) && defined(CODESET) + static int have_utf8_pcre = -1; + +- /* value can toggle based on MULTIBYTE, so don't +- * be too eager with caching */ + if (have_utf8_pcre < -1) + return 0; + +@@ -56,15 +54,11 @@ zpcre_utf8_enabled(void) + return 0; + + if ((have_utf8_pcre == -1) && +- (!strcmp(nl_langinfo(CODESET), "UTF-8"))) { +- +- if (pcre_config(PCRE_CONFIG_UTF8, &have_utf8_pcre)) ++ (pcre_config(PCRE_CONFIG_UTF8, &have_utf8_pcre))) { + have_utf8_pcre = -2; /* erk, failed to ask */ + } + +- if (have_utf8_pcre < 0) +- return 0; +- return have_utf8_pcre; ++ return (have_utf8_pcre == 1) && (!strcmp(nl_langinfo(CODESET), "UTF-8")); + + #else + return 0; +diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst +index ca13419e5..22a0b64c7 100644 +--- a/Test/V07pcre.ztst ++++ b/Test/V07pcre.ztst +@@ -162,3 +162,14 @@ + echo $match[2] ) + 0:regression for segmentation fault, workers/38307 + >test ++ ++ LANG_SAVE=$LANG ++ [[ é =~ '^.\z' ]]; echo $? ++ LANG=C ++ [[ é =~ '^..\z' ]]; echo $? ++ LANG=$LANG_SAVE ++ [[ é =~ '^.\z' ]]; echo $? ++0:swich between C/UTF-8 locales ++>0 ++>0 ++>0 +-- +2.41.0 + diff --git a/0005-zsh-port-to-pcre2.patch b/0005-zsh-port-to-pcre2.patch new file mode 100644 index 0000000..fd8ea0e --- /dev/null +++ b/0005-zsh-port-to-pcre2.patch @@ -0,0 +1,641 @@ +From b62e911341c8ec7446378b477c47da4256053dc0 Mon Sep 17 00:00:00 2001 +From: Oliver Kiddle +Date: Sat, 13 May 2023 00:53:32 +0200 +Subject: [PATCH] 51723: migrate pcre module to pcre2 + + Cherry-picked-by: Lukáš Zaoral +--- + Src/Modules/pcre.c | 223 ++++++++++++++++++--------------------------- + Test/V07pcre.ztst | 13 ++- + configure.ac | 20 ++-- + 3 files changed, 109 insertions(+), 149 deletions(-) + +diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c +index 46875a59b..079ecc2c5 100644 +--- a/Src/Modules/pcre.c ++++ b/Src/Modules/pcre.c +@@ -34,11 +34,11 @@ + #define CPCRE_PLAIN 0 + + /**/ +-#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC) +-#include ++#if defined(HAVE_PCRE2_COMPILE_8) && defined(HAVE_PCRE2_H) ++#define PCRE2_CODE_UNIT_WIDTH 8 ++#include + +-static pcre *pcre_pattern; +-static pcre_extra *pcre_hints; ++static pcre2_code *pcre_pattern; + + /**/ + static int +@@ -54,8 +54,8 @@ zpcre_utf8_enabled(void) + return 0; + + if ((have_utf8_pcre == -1) && +- (pcre_config(PCRE_CONFIG_UTF8, &have_utf8_pcre))) { +- have_utf8_pcre = -2; /* erk, failed to ask */ ++ (pcre2_config(PCRE2_CONFIG_UNICODE, &have_utf8_pcre))) { ++ have_utf8_pcre = -2; /* erk, failed to ask */ + } + + return (have_utf8_pcre == 1) && (!strcmp(nl_langinfo(CODESET), "UTF-8")); +@@ -69,115 +69,87 @@ zpcre_utf8_enabled(void) + static int + bin_pcre_compile(char *nam, char **args, Options ops, UNUSED(int func)) + { +- int pcre_opts = 0, pcre_errptr, target_len; +- const char *pcre_error; ++ uint32_t pcre_opts = 0; ++ int target_len; ++ int pcre_error; ++ PCRE2_SIZE pcre_offset; + char *target; + +- if(OPT_ISSET(ops,'a')) pcre_opts |= PCRE_ANCHORED; +- if(OPT_ISSET(ops,'i')) pcre_opts |= PCRE_CASELESS; +- if(OPT_ISSET(ops,'m')) pcre_opts |= PCRE_MULTILINE; +- if(OPT_ISSET(ops,'x')) pcre_opts |= PCRE_EXTENDED; +- if(OPT_ISSET(ops,'s')) pcre_opts |= PCRE_DOTALL; ++ if (OPT_ISSET(ops, 'a')) pcre_opts |= PCRE2_ANCHORED; ++ if (OPT_ISSET(ops, 'i')) pcre_opts |= PCRE2_CASELESS; ++ if (OPT_ISSET(ops, 'm')) pcre_opts |= PCRE2_MULTILINE; ++ if (OPT_ISSET(ops, 'x')) pcre_opts |= PCRE2_EXTENDED; ++ if (OPT_ISSET(ops, 's')) pcre_opts |= PCRE2_DOTALL; + + if (zpcre_utf8_enabled()) +- pcre_opts |= PCRE_UTF8; +- +-#ifdef HAVE_PCRE_STUDY +- if (pcre_hints) +-#ifdef PCRE_CONFIG_JIT +- pcre_free_study(pcre_hints); +-#else +- pcre_free(pcre_hints); +-#endif +- pcre_hints = NULL; +-#endif ++ pcre_opts |= PCRE2_UTF; + + if (pcre_pattern) +- pcre_free(pcre_pattern); ++ pcre2_code_free(pcre_pattern); + pcre_pattern = NULL; + + target = ztrdup(*args); + unmetafy(target, &target_len); + +- if ((int)strlen(target) != target_len) { +- zwarnnam(nam, "embedded NULs in PCRE pattern terminate pattern"); +- } +- +- pcre_pattern = pcre_compile(target, pcre_opts, &pcre_error, &pcre_errptr, NULL); ++ pcre_pattern = pcre2_compile((PCRE2_SPTR) target, (PCRE2_SIZE) target_len, ++ pcre_opts, &pcre_error, &pcre_offset, NULL); + + free(target); + + if (pcre_pattern == NULL) + { +- zwarnnam(nam, "error in regex: %s", pcre_error); ++ PCRE2_UCHAR buffer[256]; ++ pcre2_get_error_message(pcre_error, buffer, sizeof(buffer)); ++ zwarnnam(nam, "error in regex: %s", buffer); + return 1; + } + + return 0; + } + +-/**/ +-#ifdef HAVE_PCRE_STUDY +- + /**/ + static int + bin_pcre_study(char *nam, UNUSED(char **args), UNUSED(Options ops), UNUSED(int func)) + { +- const char *pcre_error; +- + if (pcre_pattern == NULL) + { + zwarnnam(nam, "no pattern has been compiled for study"); + return 1; + } +- +- if (pcre_hints) +-#ifdef PCRE_CONFIG_JIT +- pcre_free_study(pcre_hints); +-#else +- pcre_free(pcre_hints); +-#endif +- pcre_hints = NULL; + +- pcre_hints = pcre_study(pcre_pattern, 0, &pcre_error); +- if (pcre_error != NULL) +- { +- zwarnnam(nam, "error while studying regex: %s", pcre_error); +- return 1; ++ int jit = 0; ++ if (!pcre2_config(PCRE2_CONFIG_JIT, &jit) && jit) { ++ if (pcre2_jit_compile(pcre_pattern, PCRE2_JIT_COMPLETE) < 0) { ++ zwarnnam(nam, "error while studying regex"); ++ return 1; ++ } + } + + return 0; + } + +-/**/ +-#else /* !HAVE_PCRE_STUDY */ +- +-# define bin_pcre_study bin_notavail +- +-/**/ +-#endif /* !HAVE_PCRE_STUDY */ +- +-/**/ + static int +-zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, +- char *substravar, int want_offset_pair, int matchedinarr, +- int want_begin_end) ++zpcre_get_substrings(char *arg, pcre2_match_data *mdata, int captured_count, ++ char *matchvar, char *substravar, int want_offset_pair, ++ int matchedinarr, int want_begin_end) + { +- char **captures, *match_all, **matches; ++ PCRE2_SIZE *ovec; ++ char *match_all, **matches; + char offset_all[50]; + int capture_start = 1; + + if (matchedinarr) { +- /* bash-style captures[0] entire-matched string in the array */ ++ /* bash-style ovec[0] entire-matched string in the array */ + capture_start = 0; + } + +- /* captures[0] will be entire matched string, [1] first substring */ +- if (!pcre_get_substring_list(arg, ovec, captured_count, (const char ***)&captures)) { +- int nelem = arrlen(captures)-1; ++ /* ovec[0] will be entire matched string, [1] first substring */ ++ ovec = pcre2_get_ovector_pointer(mdata); ++ if (ovec) { ++ int nelem = captured_count - 1; + /* Set to the offsets of the complete match */ + if (want_offset_pair) { +- sprintf(offset_all, "%d %d", ovec[0], ovec[1]); ++ sprintf(offset_all, "%ld %ld", ovec[0], ovec[1]); + setsparam("ZPCRE_OP", ztrdup(offset_all)); + } + /* +@@ -186,7 +158,7 @@ zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, + * ovec is length 2*(1+capture_list_length) + */ + if (matchvar) { +- match_all = metafy(captures[0], ovec[1] - ovec[0], META_DUP); ++ match_all = metafy(arg + ovec[0], ovec[1] - ovec[0], META_DUP); + setsparam(matchvar, match_all); + } + /* +@@ -201,16 +173,12 @@ zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, + */ + if (substravar && + (!want_begin_end || nelem)) { +- char **x, **y; ++ char **x; + int vec_off, i; +- y = &captures[capture_start]; + matches = x = (char **) zalloc(sizeof(char *) * (captured_count+1-capture_start)); +- for (i = capture_start; i < captured_count; i++, y++) { ++ for (i = capture_start; i < captured_count; i++) { + vec_off = 2*i; +- if (*y) +- *x++ = metafy(*y, ovec[vec_off+1]-ovec[vec_off], META_DUP); +- else +- *x++ = NULL; ++ *x++ = metafy(arg + ovec[vec_off], ovec[vec_off+1]-ovec[vec_off], META_DUP); + } + *x = NULL; + setaparam(substravar, matches); +@@ -247,7 +215,8 @@ zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, + setiparam("MEND", offs + !isset(KSHARRAYS) - 1); + if (nelem) { + char **mbegin, **mend, **bptr, **eptr; +- int i, *ipair; ++ int i; ++ size_t *ipair; + + bptr = mbegin = zalloc(sizeof(char*)*(nelem+1)); + eptr = mend = zalloc(sizeof(char*)*(nelem+1)); +@@ -287,8 +256,6 @@ zpcre_get_substrings(char *arg, int *ovec, int captured_count, char *matchvar, + setaparam("mend", mend); + } + } +- +- pcre_free_substring_list((const char **)captures); + } + + return 0; +@@ -314,7 +281,8 @@ getposint(char *instr, char *nam) + static int + bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) + { +- int ret, capcount, *ovec, ovecsize, c; ++ int ret, c; ++ pcre2_match_data *pcre_mdata = NULL; + char *matched_portion = NULL; + char *plaintext = NULL; + char *receptacle = NULL; +@@ -344,36 +312,30 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) + /* For the entire match, 'Return' the offset byte positions instead of the matched string */ + if(OPT_ISSET(ops,'b')) want_offset_pair = 1; + +- if ((ret = pcre_fullinfo(pcre_pattern, pcre_hints, PCRE_INFO_CAPTURECOUNT, &capcount))) +- { +- zwarnnam(nam, "error %d in fullinfo", ret); +- return 1; +- } +- +- ovecsize = (capcount+1)*3; +- ovec = zalloc(ovecsize*sizeof(int)); +- + plaintext = ztrdup(*args); + unmetafy(plaintext, &subject_len); + + if (offset_start > 0 && offset_start >= subject_len) +- ret = PCRE_ERROR_NOMATCH; +- else +- ret = pcre_exec(pcre_pattern, pcre_hints, plaintext, subject_len, offset_start, 0, ovec, ovecsize); ++ ret = PCRE2_ERROR_NOMATCH; ++ else { ++ pcre_mdata = pcre2_match_data_create_from_pattern(pcre_pattern, NULL); ++ ret = pcre2_match(pcre_pattern, (PCRE2_SPTR) plaintext, subject_len, ++ offset_start, 0, pcre_mdata, NULL); ++ } + + if (ret==0) return_value = 0; +- else if (ret==PCRE_ERROR_NOMATCH) /* no match */; ++ else if (ret == PCRE2_ERROR_NOMATCH) /* no match */; + else if (ret>0) { +- zpcre_get_substrings(plaintext, ovec, ret, matched_portion, receptacle, ++ zpcre_get_substrings(plaintext, pcre_mdata, ret, matched_portion, receptacle, + want_offset_pair, 0, 0); + return_value = 0; + } + else { +- zwarnnam(nam, "error in pcre_exec [%d]", ret); ++ zwarnnam(nam, "error in pcre2_match [%d]", ret); + } + +- if (ovec) +- zfree(ovec, ovecsize*sizeof(int)); ++ if (pcre_mdata) ++ pcre2_match_data_free(pcre_mdata); + zsfree(plaintext); + + return return_value; +@@ -383,17 +345,19 @@ bin_pcre_match(char *nam, char **args, Options ops, UNUSED(int func)) + static int + cond_pcre_match(char **a, int id) + { +- pcre *pcre_pat; +- const char *pcre_err; ++ pcre2_code *pcre_pat = NULL; ++ int pcre_err; ++ PCRE2_SIZE pcre_erroff; + char *lhstr, *rhre, *lhstr_plain, *rhre_plain, *avar, *svar; +- int r = 0, pcre_opts = 0, pcre_errptr, capcnt, *ov, ovsize; ++ int r = 0, pcre_opts = 0; ++ pcre2_match_data *pcre_mdata = NULL; + int lhstr_plain_len, rhre_plain_len; + int return_value = 0; + + if (zpcre_utf8_enabled()) +- pcre_opts |= PCRE_UTF8; ++ pcre_opts |= PCRE2_UTF; + if (isset(REMATCHPCRE) && !isset(CASEMATCH)) +- pcre_opts |= PCRE_CASELESS; ++ pcre_opts |= PCRE2_CASELESS; + + lhstr = cond_str(a,0,0); + rhre = cond_str(a,1,0); +@@ -401,9 +365,6 @@ cond_pcre_match(char **a, int id) + rhre_plain = ztrdup(rhre); + unmetafy(lhstr_plain, &lhstr_plain_len); + unmetafy(rhre_plain, &rhre_plain_len); +- pcre_pat = NULL; +- ov = NULL; +- ovsize = 0; + + if (isset(BASHREMATCH)) { + svar = NULL; +@@ -415,27 +376,27 @@ cond_pcre_match(char **a, int id) + + switch(id) { + case CPCRE_PLAIN: +- if ((int)strlen(rhre_plain) != rhre_plain_len) { +- zwarn("embedded NULs in PCRE pattern terminate pattern"); +- } +- pcre_pat = pcre_compile(rhre_plain, pcre_opts, &pcre_err, &pcre_errptr, NULL); +- if (pcre_pat == NULL) { +- zwarn("failed to compile regexp /%s/: %s", rhre, pcre_err); ++ if (!(pcre_pat = pcre2_compile((PCRE2_SPTR) rhre_plain, ++ (PCRE2_SIZE) rhre_plain_len, pcre_opts, ++ &pcre_err, &pcre_erroff, NULL))) ++ { ++ PCRE2_UCHAR buffer[256]; ++ pcre2_get_error_message(pcre_err, buffer, sizeof(buffer)); ++ zwarn("failed to compile regexp /%s/: %s", rhre, buffer); + break; + } +- pcre_fullinfo(pcre_pat, NULL, PCRE_INFO_CAPTURECOUNT, &capcnt); +- ovsize = (capcnt+1)*3; +- ov = zalloc(ovsize*sizeof(int)); +- r = pcre_exec(pcre_pat, NULL, lhstr_plain, lhstr_plain_len, 0, 0, ov, ovsize); +- /* r < 0 => error; r==0 match but not enough size in ov ++ pcre_mdata = pcre2_match_data_create_from_pattern(pcre_pat, NULL); ++ r = pcre2_match(pcre_pat, (PCRE2_SPTR8) lhstr_plain, lhstr_plain_len, ++ 0, 0, pcre_mdata, NULL); ++ /* r < 0 => error; r==0 match but not enough size in match data + * r > 0 => (r-1) substrings found; r==1 => no substrings + */ + if (r==0) { +- zwarn("reportable zsh problem: pcre_exec() returned 0"); ++ zwarn("reportable zsh problem: pcre2_match() returned 0"); + return_value = 1; + break; + } +- else if (r==PCRE_ERROR_NOMATCH) { ++ else if (r == PCRE2_ERROR_NOMATCH) { + return_value = 0; /* no match */ + break; + } +@@ -444,7 +405,7 @@ cond_pcre_match(char **a, int id) + break; + } + else if (r>0) { +- zpcre_get_substrings(lhstr_plain, ov, r, svar, avar, 0, ++ zpcre_get_substrings(lhstr_plain, pcre_mdata, r, svar, avar, 0, + isset(BASHREMATCH), + !isset(BASHREMATCH)); + return_value = 1; +@@ -457,10 +418,10 @@ cond_pcre_match(char **a, int id) + free(lhstr_plain); + if(rhre_plain) + free(rhre_plain); ++ if (pcre_mdata) ++ pcre2_match_data_free(pcre_mdata); + if (pcre_pat) +- pcre_free(pcre_pat); +- if (ov) +- zfree(ov, ovsize*sizeof(int)); ++ pcre2_code_free(pcre_pat); + + return return_value; + } +@@ -489,11 +450,11 @@ static struct builtin bintab[] = { + + static struct features module_features = { + bintab, sizeof(bintab)/sizeof(*bintab), +-#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC) ++#if defined(HAVE_PCRE2_COMPILE_8) && defined(HAVE_PCRE2_H) + cotab, sizeof(cotab)/sizeof(*cotab), +-#else /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */ ++#else /* !(HAVE_PCRE2_COMPILE_8 && HAVE_PCRE2_H) */ + NULL, 0, +-#endif /* !(HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC) */ ++#endif /* !(HAVE_PCRE2_COMPILE_8 && HAVE_PCRE2_H) */ + NULL, 0, + NULL, 0, + 0 +@@ -540,19 +501,9 @@ cleanup_(Module m) + int + finish_(UNUSED(Module m)) + { +-#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC) +-#ifdef HAVE_PCRE_STUDY +- if (pcre_hints) +-#ifdef PCRE_CONFIG_JIT +- pcre_free_study(pcre_hints); +-#else +- pcre_free(pcre_hints); +-#endif +- pcre_hints = NULL; +-#endif +- ++#if defined(HAVE_PCRE2_COMPILE_8) && defined(HAVE_PCRE2_H) + if (pcre_pattern) +- pcre_free(pcre_pattern); ++ pcre2_code_free(pcre_pattern); + pcre_pattern = NULL; + #endif + +diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst +index 22a0b64c7..6eb366964 100644 +--- a/Test/V07pcre.ztst ++++ b/Test/V07pcre.ztst +@@ -117,12 +117,17 @@ + >78884; ZPCRE_OP: 25 30 + >90210; ZPCRE_OP: 31 36 + +-# Embedded NULs allowed in plaintext, but not in RE (although \0 as two-chars allowed) ++# Embedded NULs allowed in plaintext, in RE, pcre supports \0 as two-chars + [[ $'a\0bc\0d' =~ '^(a\0.)(.+)$' ]] + print "${#MATCH}; ${#match[1]}; ${#match[2]}" + 0:ensure ASCII NUL passes in and out of matched plaintext + >6; 3; 3 + ++# PCRE2 supports NULs also in the RE ++ [[ $'a\0b\0c' =~ $'^(.\0)+' ]] && print "${#MATCH}; ${#match[1]}" ++0:ensure ASCII NUL works also in the regex ++>4; 2 ++ + # Ensure the long-form infix operator works + [[ foo -pcre-match ^f..$ ]] + print $? +@@ -169,7 +174,11 @@ + [[ é =~ '^..\z' ]]; echo $? + LANG=$LANG_SAVE + [[ é =~ '^.\z' ]]; echo $? +-0:swich between C/UTF-8 locales ++0:switch between C/UTF-8 locales + >0 + >0 + >0 ++ ++ [[ abc =~ 'a(d*)bc' ]] && print "$#MATCH; $#match; ${#match[1]}" ++0:empty capture ++>3; 1; 0 +diff --git a/configure.ac b/configure.ac +index d8a17791a..4710d1659 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -438,7 +438,7 @@ fi], + + dnl Do you want to look for pcre support? + AC_ARG_ENABLE(pcre, +-AS_HELP_STRING([--enable-pcre],[enable the search for the pcre library (may create run-time library dependencies)])) ++AS_HELP_STRING([--enable-pcre],[enable the search for the pcre2 library (may create run-time library dependencies)])) + + dnl Do you want to look for capability support? + AC_ARG_ENABLE(cap, +@@ -652,13 +652,12 @@ AC_HEADER_SYS_WAIT + + oldcflags="$CFLAGS" + if test x$enable_pcre = xyes; then +-AC_CHECK_PROG([PCRECONF], pcre-config, pcre-config) +-dnl Typically (meaning on this single RedHat 9 box in front of me) +-dnl pcre-config --cflags produces a -I output which needs to go into ++AC_CHECK_PROG([PCRECONF], pcre2-config, pcre2-config) ++dnl pcre2-config --cflags may produce a -I output which needs to go into + dnl CPPFLAGS else configure's preprocessor tests don't pick it up, + dnl producing a warning. +-if test "x$ac_cv_prog_PCRECONF" = xpcre-config; then +- CPPFLAGS="$CPPFLAGS `pcre-config --cflags`" ++if test "x$ac_cv_prog_PCRECONF" = xpcre2-config; then ++ CPPFLAGS="$CPPFLAGS `pcre2-config --cflags`" + fi + fi + +@@ -668,9 +667,10 @@ AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ + locale.h errno.h stdio.h stdarg.h varargs.h stdlib.h \ + unistd.h sys/capability.h \ + utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h sys/mman.h \ +- netinet/in_systm.h pcre.h langinfo.h wchar.h stddef.h \ ++ netinet/in_systm.h langinfo.h wchar.h stddef.h \ + sys/stropts.h iconv.h ncurses.h ncursesw/ncurses.h \ + ncurses/ncurses.h) ++AC_CHECK_HEADERS([pcre2.h],,,[#define PCRE2_CODE_UNIT_WIDTH 8]) + if test x$dynamic = xyes; then + AC_CHECK_HEADERS(dlfcn.h) + AC_CHECK_HEADERS(dl.h) +@@ -948,9 +948,7 @@ if test "x$ac_found_iconv" = "xyes"; then + fi + + if test x$enable_pcre = xyes; then +-dnl pcre-config should probably be employed here +-dnl AC_SEARCH_LIBS(pcre_compile, pcre) +- LIBS="`$ac_cv_prog_PCRECONF --libs` $LIBS" ++ LIBS="`$ac_cv_prog_PCRECONF --libs8` $LIBS" + fi + + dnl --------------------- +@@ -1313,7 +1311,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ + pathconf sysconf \ + tgetent tigetflag tigetnum tigetstr setupterm initscr resize_term \ + getcchar setcchar waddwstr wget_wch win_wch use_default_colors \ +- pcre_compile pcre_study pcre_exec \ ++ pcre2_compile_8 \ + nl_langinfo \ + erand48 open_memstream \ + posix_openpt \ +-- +2.41.0 + +From 10bdbd8b5b0b43445aff23dcd412f25cf6aa328a Mon Sep 17 00:00:00 2001 +From: Jun-ichi Takimoto +Date: Tue, 20 Jun 2023 18:14:27 +0900 +Subject: [PATCH] 51877: do not build pcre module if pcre2-config is not found + + Cherry-picked-by: Lukáš Zaoral +--- + Src/Modules/pcre.mdd | 2 +- + configure.ac | 31 +++++++++++++++++++------------ + 2 files changed, 20 insertions(+), 13 deletions(-) + +diff --git a/Src/Modules/pcre.mdd b/Src/Modules/pcre.mdd +index 6eb3c691b..3e1579117 100644 +--- a/Src/Modules/pcre.mdd ++++ b/Src/Modules/pcre.mdd +@@ -1,5 +1,5 @@ + name=zsh/pcre +-link=`if test x$enable_pcre = xyes && (pcre-config --version >/dev/null 2>/dev/null); then echo dynamic; else echo no; fi` ++link=`if test x$enable_pcre = xyes; then echo dynamic; else echo no; fi` + load=no + + autofeatures="b:pcre_compile b:pcre_study b:pcre_match" +diff --git a/configure.ac b/configure.ac +index ba76f9a60..c5263035e 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -440,6 +440,17 @@ dnl Do you want to look for pcre support? + AC_ARG_ENABLE(pcre, + AS_HELP_STRING([--enable-pcre],[enable the search for the pcre2 library (may create run-time library dependencies)])) + ++AC_ARG_VAR(PCRE_CONFIG, [pathname of pcre2-config if it is not in PATH]) ++if test "x$enable_pcre" = xyes; then ++ AC_CHECK_PROG([PCRE_CONFIG], pcre2-config, pcre2-config) ++ if test "x$PCRE_CONFIG" = x; then ++ enable_pcre=no ++ AC_MSG_WARN([pcre2-config not found: pcre module is disabled.]) ++ AC_MSG_NOTICE( ++ [Set PCRE_CONFIG to pathname of pcre2-config if it is not in PATH.]) ++ fi ++fi ++ + dnl Do you want to look for capability support? + AC_ARG_ENABLE(cap, + AS_HELP_STRING([--enable-cap],[enable the search for POSIX capabilities (may require additional headers to be added by hand)])) +@@ -655,15 +666,12 @@ AC_HEADER_DIRENT + AC_HEADER_STAT + AC_HEADER_SYS_WAIT + +-oldcflags="$CFLAGS" +-if test x$enable_pcre = xyes; then +-AC_CHECK_PROG([PCRECONF], pcre2-config, pcre2-config) + dnl pcre2-config --cflags may produce a -I output which needs to go into + dnl CPPFLAGS else configure's preprocessor tests don't pick it up, + dnl producing a warning. +-if test "x$ac_cv_prog_PCRECONF" = xpcre2-config; then +- CPPFLAGS="$CPPFLAGS `pcre2-config --cflags`" +-fi ++if test "x$enable_pcre" = xyes; then ++ CPPFLAGS="`$PCRE_CONFIG --cflags` $CPPFLAGS" ++ AC_CHECK_HEADERS([pcre2.h],,,[#define PCRE2_CODE_UNIT_WIDTH 8]) + fi + + AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ +@@ -675,7 +683,6 @@ AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ + netinet/in_systm.h langinfo.h wchar.h stddef.h \ + sys/stropts.h iconv.h ncurses.h ncursesw/ncurses.h \ + ncurses/ncurses.h) +-AC_CHECK_HEADERS([pcre2.h],,,[#define PCRE2_CODE_UNIT_WIDTH 8]) + if test x$dynamic = xyes; then + AC_CHECK_HEADERS(dlfcn.h) + AC_CHECK_HEADERS(dl.h) +@@ -952,10 +959,6 @@ if test "x$ac_found_iconv" = "xyes"; then + [Define as const if the declaration of iconv() needs const.]) + fi + +-if test x$enable_pcre = xyes; then +- LIBS="`$ac_cv_prog_PCRECONF --libs8` $LIBS" +-fi +- + dnl --------------------- + dnl CHECK TERMCAP LIBRARY + dnl --------------------- +@@ -1316,7 +1319,6 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ + pathconf sysconf \ + tgetent tigetflag tigetnum tigetstr setupterm initscr resize_term \ + getcchar setcchar waddwstr wget_wch win_wch use_default_colors \ +- pcre2_compile_8 \ + nl_langinfo \ + erand48 open_memstream \ + posix_openpt \ +@@ -1371,6 +1373,11 @@ if test x$zsh_cv_func_realpath_accepts_null = xyes; then + AC_DEFINE(REALPATH_ACCEPTS_NULL) + fi + ++if test x$enable_pcre = xyes; then ++ LIBS="`$PCRE_CONFIG --libs8` $LIBS" ++ AC_CHECK_FUNCS(pcre2_compile_8) ++fi ++ + if test x$enable_cap = xyes; then + AC_CHECK_FUNCS(cap_get_proc) + fi +-- +2.42.0 + diff --git a/0006-zsh-support-texinfo-7.0.patch b/0006-zsh-support-texinfo-7.0.patch new file mode 100644 index 0000000..c68bd26 --- /dev/null +++ b/0006-zsh-support-texinfo-7.0.patch @@ -0,0 +1,53 @@ +From ecd3f9c9506c7720dc6c0833dc5d5eb00e4459c4 Mon Sep 17 00:00:00 2001 +From: Jun-ichi Takimoto +Date: Mon, 19 Jun 2023 11:19:25 +0900 +Subject: [PATCH] 51862: support texinfo-7.0 + +Upstream-commit: ecd3f9c9506c7720dc6c0833dc5d5eb00e4459c4 +Cherry-picked-by: Lukáš Zaoral +--- + Doc/Makefile.in | 3 ++- + configure.ac | 5 +++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/Doc/Makefile.in b/Doc/Makefile.in +index 136b080d6..dabe11fe3 100644 +--- a/Doc/Makefile.in ++++ b/Doc/Makefile.in +@@ -43,6 +43,7 @@ TEXI2DVI = @TEXI2DVI@ + DVIPS = dvips + TEXI2PDF = @TEXI2PDF@ + TEXI2HTML = @TEXI2HTML@ ++SET_TEXI2ANY_VAR = @SET_TEXI2ANY_VAR@ + PAPERSIZE = @PAPERSIZE@ + + .SUFFIXES: .yo .1 +@@ -266,7 +267,7 @@ texi2html.conf: $(sdir_top)/Config/version.mk + d=`echo $(VERSION_DATE)`; \ + v="Zsh version $(VERSION), released on $$d."; \ + case '$(TEXI2HTML)' in \ +- *texi2any*) echo "set_from_init_file('PRE_BODY_CLOSE','$$v');" ;; \ ++ *texi2any*) echo "$(SET_TEXI2ANY_VAR)('PRE_BODY_CLOSE','$$v');" ;; \ + *) echo "\$$PRE_BODY_CLOSE = '$$v';" ;; \ + esac > $@ + +diff --git a/configure.ac b/configure.ac +index 4710d1659..ba76f9a60 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -623,7 +623,12 @@ fi + + if test x"$TEXI2HTML" = xtexi2any; then + TEXI2HTML='texi2any -c TEXI2HTML=1' ++ case `texi2any --version 2>/dev/null | sed -e 's/^.*) *//' -e 1q` in ++ [[1-6]].*) SET_TEXI2ANY_VAR=set_from_init_file ;; ++ *) SET_TEXI2ANY_VAR=texinfo_set_from_init_file ;; ++ esac + fi ++AC_SUBST(SET_TEXI2ANY_VAR) + + case "$LC_PAPER" in + ??_US*) PAPERSIZE=us ;; +-- +2.42.0 + diff --git a/0007-zsh-configure-c99.patch b/0007-zsh-configure-c99.patch new file mode 100644 index 0000000..c4b3623 --- /dev/null +++ b/0007-zsh-configure-c99.patch @@ -0,0 +1,44 @@ +Avoid incompatible pointer types in terminfo global variable checks. +Some compilers reject these incompatible pointer types, causing the +checks to always fail, when these variables are in fact available. + +Submitted upstream: + +diff --git a/configure.ac b/configure.ac +index a58242f453b4a8f3..5534f42df14eb28c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1769,27 +1769,27 @@ if test x$zsh_cv_path_term_header != xnone; then + fi + + AC_MSG_CHECKING(if boolcodes is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = boolcodes; puts(*test);]])],[AC_DEFINE(HAVE_BOOLCODES) boolcodes=yes],[boolcodes=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)boolcodes; puts(*test);]])],[AC_DEFINE(HAVE_BOOLCODES) boolcodes=yes],[boolcodes=no]) + AC_MSG_RESULT($boolcodes) + + AC_MSG_CHECKING(if numcodes is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = numcodes; puts(*test);]])],[AC_DEFINE(HAVE_NUMCODES) numcodes=yes],[numcodes=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)numcodes; puts(*test);]])],[AC_DEFINE(HAVE_NUMCODES) numcodes=yes],[numcodes=no]) + AC_MSG_RESULT($numcodes) + + AC_MSG_CHECKING(if strcodes is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = strcodes; puts(*test);]])],[AC_DEFINE(HAVE_STRCODES) strcodes=yes],[strcodes=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)strcodes; puts(*test);]])],[AC_DEFINE(HAVE_STRCODES) strcodes=yes],[strcodes=no]) + AC_MSG_RESULT($strcodes) + + AC_MSG_CHECKING(if boolnames is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = boolnames; puts(*test);]])],[AC_DEFINE(HAVE_BOOLNAMES) boolnames=yes],[boolnames=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)boolnames; puts(*test);]])],[AC_DEFINE(HAVE_BOOLNAMES) boolnames=yes],[boolnames=no]) + AC_MSG_RESULT($boolnames) + + AC_MSG_CHECKING(if numnames is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = numnames; puts(*test);]])],[AC_DEFINE(HAVE_NUMNAMES) numnames=yes],[numnames=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)numnames; puts(*test);]])],[AC_DEFINE(HAVE_NUMNAMES) numnames=yes],[numnames=no]) + AC_MSG_RESULT($numnames) + + AC_MSG_CHECKING(if strnames is available) +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = strnames; puts(*test);]])],[AC_DEFINE(HAVE_STRNAMES) strnames=yes],[strnames=no]) ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$term_includes]], [[char **test = (char **)strnames; puts(*test);]])],[AC_DEFINE(HAVE_STRNAMES) strnames=yes],[strnames=no]) + AC_MSG_RESULT($strnames) + + dnl There are apparently defective terminal library headers on some diff --git a/0008-zsh-deletefilelist-segfault.patch b/0008-zsh-deletefilelist-segfault.patch new file mode 100644 index 0000000..8abaab1 --- /dev/null +++ b/0008-zsh-deletefilelist-segfault.patch @@ -0,0 +1,42 @@ +From d3edf318306e37d2d96c4e4ea442d10207722e94 Mon Sep 17 00:00:00 2001 +From: Bart Schaefer +Date: Sun, 12 Feb 2023 09:52:39 -0800 +Subject: [PATCH] 51404: Nullify filelist after deleting (fix segfault) + +Cherry-picked-by: Lukáš Zaoral +Upstream-commit: d3edf318306e37d2d96c4e4ea442d10207722e94 +--- + Src/jobs.c | 8 ++++++-- + 1 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/Src/jobs.c b/Src/jobs.c +index 4863962b9..59ddd952e 100644 +--- a/Src/jobs.c ++++ b/Src/jobs.c +@@ -1372,8 +1372,10 @@ cleanfilelists(void) + + DPUTS(shell_exiting >= 0, "BUG: cleanfilelists() before exit"); + +- for (i = 1; i <= maxjob; i++) ++ for (i = 1; i <= maxjob; i++) { + deletefilelist(jobtab[i].filelist, 0); ++ jobtab[i].filelist = 0; ++ } + } + + /**/ +@@ -1531,8 +1533,10 @@ havefiles(void) + int i; + + for (i = 1; i <= maxjob; i++) +- if (jobtab[i].stat && jobtab[i].filelist) ++ if (jobtab[i].stat && jobtab[i].filelist && ++ peekfirst(jobtab[i].filelist)) { + return 1; ++ } + return 0; + + } +-- +2.43.0 + diff --git a/SOURCES/0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch b/SOURCES/0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch deleted file mode 100644 index 0345288..0000000 --- a/SOURCES/0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch +++ /dev/null @@ -1,148 +0,0 @@ -From ddb6c5b4c0ab9c6a7404112d367f0c7cc400ceec Mon Sep 17 00:00:00 2001 -From: Anthony Sottile -Date: Mon, 3 Sep 2018 14:39:25 +0000 -Subject: [PATCH] CVE-2018-0502, CVE-2018-13259: Fix two security issues in - shebang line parsing. - -See NEWS for more information. - -Patch by Anthony Sottile and Buck Evan. - -Upstream-commit: 1c4c7b6a4d17294df028322b70c53803a402233d -Signed-off-by: Kamil Dudka ---- - Etc/FAQ.yo | 2 +- - Src/exec.c | 36 ++++++++++++++++++++---------------- - Test/A05execution.ztst | 22 ++++++++++++++++++++++ - 3 files changed, 43 insertions(+), 17 deletions(-) - -diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo -index 72ff7fa..8552fe7 100644 ---- a/Etc/FAQ.yo -+++ b/Etc/FAQ.yo -@@ -306,7 +306,7 @@ sect(On what machines will it run?) - - sect(What's the latest version?) - -- Zsh 5.5.1 is the latest production version. For details of all the -+ Zsh 5.6 is the latest production version. For details of all the - changes, see the NEWS file in the source distribution. - - A beta of the next version is sometimes available. Development of zsh is -diff --git a/Src/exec.c b/Src/exec.c -index 216057a..0908a1a 100644 ---- a/Src/exec.c -+++ b/Src/exec.c -@@ -453,7 +453,7 @@ execcursh(Estate state, int do_exec) - - /* execve after handling $_ and #! */ - --#define POUNDBANGLIMIT 64 -+#define POUNDBANGLIMIT 128 - - /**/ - static int -@@ -494,18 +494,20 @@ zexecve(char *pth, char **argv, char **newenvp) - if ((fd = open(pth, O_RDONLY|O_NOCTTY)) >= 0) { - argv0 = *argv; - *argv = pth; -- execvebuf[0] = '\0'; -+ memset(execvebuf, '\0', POUNDBANGLIMIT + 1); - ct = read(fd, execvebuf, POUNDBANGLIMIT); - close(fd); - if (ct >= 0) { -- if (execvebuf[0] == '#') { -- if (execvebuf[1] == '!') { -- for (t0 = 0; t0 != ct; t0++) -- if (execvebuf[t0] == '\n') -- break; -+ if (ct >= 2 && execvebuf[0] == '#' && execvebuf[1] == '!') { -+ for (t0 = 0; t0 != ct; t0++) -+ if (execvebuf[t0] == '\n') -+ break; -+ if (t0 == ct) -+ zerr("%s: bad interpreter: %s: %e", pth, -+ execvebuf + 2, eno); -+ else { - while (inblank(execvebuf[t0])) - execvebuf[t0--] = '\0'; -- execvebuf[POUNDBANGLIMIT] = '\0'; - for (ptr = execvebuf + 2; *ptr && *ptr == ' '; ptr++); - for (ptr2 = ptr; *ptr && *ptr != ' '; ptr++); - if (eno == ENOENT) { -@@ -514,10 +516,16 @@ zexecve(char *pth, char **argv, char **newenvp) - *ptr = '\0'; - if (*ptr2 != '/' && - (pprog = pathprog(ptr2, NULL))) { -- argv[-2] = ptr2; -- argv[-1] = ptr + 1; -- winch_unblock(); -- execve(pprog, argv - 2, newenvp); -+ if (ptr == execvebuf + t0 + 1) { -+ argv[-1] = ptr2; -+ winch_unblock(); -+ execve(pprog, argv - 1, newenvp); -+ } else { -+ argv[-2] = ptr2; -+ argv[-1] = ptr + 1; -+ winch_unblock(); -+ execve(pprog, argv - 2, newenvp); -+ } - } - zerr("%s: bad interpreter: %s: %e", pth, ptr2, - eno); -@@ -532,10 +540,6 @@ zexecve(char *pth, char **argv, char **newenvp) - winch_unblock(); - execve(ptr2, argv - 1, newenvp); - } -- } else if (eno == ENOEXEC) { -- argv[-1] = "sh"; -- winch_unblock(); -- execve("/bin/sh", argv - 1, newenvp); - } - } else if (eno == ENOEXEC) { - for (t0 = 0; t0 != ct; t0++) -diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst -index 0804691..fb39d05 100644 ---- a/Test/A05execution.ztst -+++ b/Test/A05execution.ztst -@@ -12,7 +12,14 @@ - - print '#!/bin/sh\necho This is dir2' >dir2/tstcmd - -+ print -n '#!sh\necho This is slashless' >tstcmd-slashless -+ print -n '#!echo foo\necho This is arg' >tstcmd-arg -+ print '#!xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxnyyy' >tstcmd-interp-too-long -+ print '#!/bin/sh\necho should not execute; exit 1' >xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn -+ - chmod 755 tstcmd dir1/tstcmd dir2/tstcmd -+ chmod 755 tstcmd-slashless tstcmd-arg tstcmd-interp-too-long -+ chmod 755 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxn - - %test - ./tstcmd -@@ -33,6 +40,21 @@ - 0:path (2) - >This is top - -+ PATH=/bin:${ZTST_testdir}/command.tmp/ tstcmd-slashless -+0:path (3) -+>This is slashless -+ -+ PATH=/bin:${ZTST_testdir}/command.tmp tstcmd-arg -+0:path (4) -+*>foo */command.tmp/tstcmd-arg -+ -+ path=(/bin ${ZTST_testdir}/command.tmp/) -+ tstcmd-interp-too-long 2>&1; echo "status $?" -+ path=($storepath) -+0:path (5) -+*>*tstcmd-interp-too-long: bad interpreter: x*xn: no such file or directory -+>status 127 -+ - functst() { print $# arguments:; print -l $*; } - functst "Eines Morgens" "als Gregor Samsa" - functst "" --- -2.17.1 - diff --git a/SOURCES/0002-zsh-5.5.1-static-analysis.patch b/SOURCES/0002-zsh-5.5.1-static-analysis.patch deleted file mode 100644 index 4bec6e1..0000000 --- a/SOURCES/0002-zsh-5.5.1-static-analysis.patch +++ /dev/null @@ -1,266 +0,0 @@ -From bc943b78268ad633f79756639d4295f7b61dbedd Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 7 Nov 2018 14:04:52 +0100 -Subject: [PATCH 1/5] 43791: File descriptor could be closed twice in clone - -Upstream-commit: a8cc017c74a916b690dc074c299faf4bd24b5af4 -Signed-off-by: Kamil Dudka - -Error: USE_AFTER_FREE (CWE-825): -zsh-5.5.1/Src/Modules/clone.c:71: closed_arg: "close(int)" closes "ttyfd". -zsh-5.5.1/Src/Modules/clone.c:99: double_close: Calling "close(int)" closes handle "ttyfd" which has already been closed. - 97| setsparam("TTY", ztrdup(ttystrname)); - 98| } - 99|-> close(ttyfd); -100| if (pid < 0) { -101| zerrnam(nam, "fork failed: %e", errno); ---- - Src/Modules/clone.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/Src/Modules/clone.c b/Src/Modules/clone.c -index 9304292..dfd8e8a 100644 ---- a/Src/Modules/clone.c -+++ b/Src/Modules/clone.c -@@ -96,7 +96,8 @@ bin_clone(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) - init_io(NULL); - setsparam("TTY", ztrdup(ttystrname)); - } -- close(ttyfd); -+ else -+ close(ttyfd); - if (pid < 0) { - zerrnam(nam, "fork failed: %e", errno); - return 1; --- -2.17.2 - - -From 6096988f02635ed336a056e3670b63070400e6bc Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 7 Nov 2018 14:04:53 +0100 -Subject: [PATCH 2/5] 43793: computil could overrun buffer - -Upstream-commit: 031afe420725e328e9d7742be69ef0bd81c62b9a -Signed-off-by: Kamil Dudka - -Error: BUFFER_SIZE (CWE-120): -zsh-5.5.1/Src/Zle/computil.c:564: overlapping_buffer: The source buffer "str->str + 2" potentially overlaps with the destination buffer "str->str", which results in undefined behavior for "strcpy". -zsh-5.5.1/Src/Zle/computil.c:564: remediation: Replace "strcpy(dest, src)" with "memmove(dest, src, strlen(src)+1)". -562| str->str = ztrdup(str->str); -563| if (hide[1] && str->str[0] == '-' && str->str[1] == '-') -564|-> strcpy(str->str, str->str + 2); -565| else if (str->str[0] == '-' || str->str[0] == '+') -566| strcpy(str->str, str->str + 1); - -Error: BUFFER_SIZE (CWE-120): -zsh-5.5.1/Src/Zle/computil.c:566: overlapping_buffer: The source buffer "str->str + 1" potentially overlaps with the destination buffer "str->str", which results in undefined behavior for "strcpy". -zsh-5.5.1/Src/Zle/computil.c:566: remediation: Replace "strcpy(dest, src)" with "memmove(dest, src, strlen(src)+1)". -564| strcpy(str->str, str->str + 2); -565| else if (str->str[0] == '-' || str->str[0] == '+') -566|-> strcpy(str->str, str->str + 1); -567| } -568| } ---- - Src/Zle/computil.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c -index 5526e0a..cb1c010 100644 ---- a/Src/Zle/computil.c -+++ b/Src/Zle/computil.c -@@ -561,9 +561,9 @@ cd_init(char *nam, char *hide, char *mlen, char *sep, - if (str->str == str->match) - str->str = ztrdup(str->str); - if (hide[1] && str->str[0] == '-' && str->str[1] == '-') -- strcpy(str->str, str->str + 2); -+ memmove(str->str, str->str + 2, strlen(str->str) - 1); - else if (str->str[0] == '-' || str->str[0] == '+') -- strcpy(str->str, str->str + 1); -+ memmove(str->str, str->str + 1, strlen(str->str)); - } - } - for (ap = args; *args && --- -2.17.2 - - -From 29445bdf10714bd41d2124d3c31cc16c1f682854 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 7 Nov 2018 14:04:54 +0100 -Subject: [PATCH 3/5] 43723: file descriptor could leak on fork error - -Upstream-commit: d1095bdf744c190c7e8ff126ba02caea8f63880d -Signed-off-by: Kamil Dudka - -Error: RESOURCE_LEAK (CWE-772): -zsh-5.5.1/Src/exec.c:4680: open_fn: Returning handle opened by "open". -zsh-5.5.1/Src/exec.c:4680: var_assign: Assigning: "fd" = handle returned from "open(nam, 449, 384)". -zsh-5.5.1/Src/exec.c:4810: leaked_handle: Handle variable "fd" going out of scope leaks the handle. -4808| /* fork or open error */ -4809| child_unblock(); -4810|-> return nam; -4811| } else if (pid) { -4812| int os; ---- - Src/exec.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/Src/exec.c b/Src/exec.c -index 0908a1a..8045db2 100644 ---- a/Src/exec.c -+++ b/Src/exec.c -@@ -4722,7 +4722,8 @@ getoutputfile(char *cmd, char **eptr) - } - - if ((cmdoutpid = pid = zfork(NULL)) == -1) { -- /* fork or open error */ -+ /* fork error */ -+ close(fd); - child_unblock(); - return nam; - } else if (pid) { --- -2.17.2 - - -From afb4192a75066f86ce7051a72c0feb7b80c0cdd8 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 7 Nov 2018 14:04:55 +0100 -Subject: [PATCH 4/5] 43789: possible use after free clearing up math func from - module - -Upstream-commit: e27175c7c8cdfeb4e28d4ff21eb51aa003d70a03 -Signed-off-by: Kamil Dudka - -Error: USE_AFTER_FREE (CWE-825): -zsh-5.5.1/Src/module.c:1390: freed_arg: "deletemathfunc" frees "f". -zsh-5.5.1/Src/module.c:1352:6: freed_arg: "zfree" frees parameter "f". -zsh-5.5.1/Src/mem.c:1888:5: freed_arg: "free" frees parameter "p". -zsh-5.5.1/Src/module.c:1394: deref_after_free: Dereferencing freed pointer "f". -1392| ret = 1; -1393| } else { -1394|-> f->flags &= ~MFF_ADDED; -1395| } -1396| } ---- - Src/module.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/Src/module.c b/Src/module.c -index 4ae7831..33d75eb 100644 ---- a/Src/module.c -+++ b/Src/module.c -@@ -1390,8 +1390,6 @@ setmathfuncs(char const *nam, MathFunc f, int size, int *e) - if (deletemathfunc(f)) { - zwarnnam(nam, "math function `%s' already deleted", f->name); - ret = 1; -- } else { -- f->flags &= ~MFF_ADDED; - } - } - f++; --- -2.17.2 - - -From 4553645c00d9a2e81a79e2014b106f6590500287 Mon Sep 17 00:00:00 2001 -From: Kamil Dudka -Date: Wed, 7 Nov 2018 14:04:56 +0100 -Subject: [PATCH 5/5] 43790: failed mailstat could leak memory - -Upstream-commit: d50e204b0c4c10164a711bf640500e46987de9c3 -Signed-off-by: Kamil Dudka - -Error: RESOURCE_LEAK (CWE-772): -zsh-5.5.1/Src/utils.c:7406: alloc_fn: Storage is returned from allocation function "appstr". -zsh-5.5.1/Src/string.c:200:5: alloc_fn: Storage is returned from allocation function "realloc". -zsh-5.5.1/Src/string.c:200:5: identity_transfer: Passing "realloc(base, strlen(base) + strlen(append) + 1UL)" as argument 1 to function "strcat", which returns that argument. -zsh-5.5.1/Src/string.c:200:5: return_alloc_fn: Directly returning storage allocated by "strcat". -zsh-5.5.1/Src/utils.c:7406: var_assign: Assigning: "dir" = storage returned from "appstr(ztrdup(path), "/cur")". -zsh-5.5.1/Src/utils.c:7407: noescape: Resource "dir" is not freed or pointed-to in "stat". -zsh-5.5.1/Src/utils.c:7407: leaked_storage: Variable "dir" going out of scope leaks the storage it points to. -7405| /* See if cur/ is present */ -7406| dir = appstr(ztrdup(path), "/cur"); -7407|-> if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -7408| st_ret.st_atime = st_tmp.st_atime; -7409| - -Error: RESOURCE_LEAK (CWE-772): -zsh-5.5.1/Src/utils.c:7412: alloc_fn: Storage is returned from allocation function "appstr". -zsh-5.5.1/Src/string.c:200:5: alloc_fn: Storage is returned from allocation function "realloc". -zsh-5.5.1/Src/string.c:200:5: identity_transfer: Passing "realloc(base, strlen(base) + strlen(append) + 1UL)" as argument 1 to function "strcat", which returns that argument. -zsh-5.5.1/Src/string.c:200:5: return_alloc_fn: Directly returning storage allocated by "strcat". -zsh-5.5.1/Src/utils.c:7412: var_assign: Assigning: "dir" = storage returned from "appstr(dir, "/tmp")". -zsh-5.5.1/Src/utils.c:7413: noescape: Resource "dir" is not freed or pointed-to in "stat". -zsh-5.5.1/Src/utils.c:7413: leaked_storage: Variable "dir" going out of scope leaks the storage it points to. -7411| dir[plen] = 0; -7412| dir = appstr(dir, "/tmp"); -7413|-> if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -7414| st_ret.st_mtime = st_tmp.st_mtime; -7415| - -Error: RESOURCE_LEAK (CWE-772): -zsh-5.5.1/Src/utils.c:7418: alloc_fn: Storage is returned from allocation function "appstr". -zsh-5.5.1/Src/string.c:200:5: alloc_fn: Storage is returned from allocation function "realloc". -zsh-5.5.1/Src/string.c:200:5: identity_transfer: Passing "realloc(base, strlen(base) + strlen(append) + 1UL)" as argument 1 to function "strcat", which returns that argument. -zsh-5.5.1/Src/string.c:200:5: return_alloc_fn: Directly returning storage allocated by "strcat". -zsh-5.5.1/Src/utils.c:7418: var_assign: Assigning: "dir" = storage returned from "appstr(dir, "/new")". -zsh-5.5.1/Src/utils.c:7419: noescape: Resource "dir" is not freed or pointed-to in "stat". -zsh-5.5.1/Src/utils.c:7419: leaked_storage: Variable "dir" going out of scope leaks the storage it points to. -7417| dir[plen] = 0; -7418| dir = appstr(dir, "/new"); -7419|-> if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -7420| st_ret.st_mtime = st_tmp.st_mtime; -7421| ---- - Src/utils.c | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - -diff --git a/Src/utils.c b/Src/utils.c -index b418517..492babc 100644 ---- a/Src/utils.c -+++ b/Src/utils.c -@@ -7404,19 +7404,28 @@ mailstat(char *path, struct stat *st) - - /* See if cur/ is present */ - dir = appstr(ztrdup(path), "/cur"); -- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -+ if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) { -+ zsfree(dir); -+ return 0; -+ } - st_ret.st_atime = st_tmp.st_atime; - - /* See if tmp/ is present */ - dir[plen] = 0; - dir = appstr(dir, "/tmp"); -- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -+ if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) { -+ zsfree(dir); -+ return 0; -+ } - st_ret.st_mtime = st_tmp.st_mtime; - - /* And new/ */ - dir[plen] = 0; - dir = appstr(dir, "/new"); -- if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0; -+ if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) { -+ zsfree(dir); -+ return 0; -+ } - st_ret.st_mtime = st_tmp.st_mtime; - - #if THERE_IS_EXACTLY_ONE_MAILDIR_IN_MAILPATH -@@ -7428,6 +7437,7 @@ mailstat(char *path, struct stat *st) - st_tmp.st_atime == st_new_last.st_atime && - st_tmp.st_mtime == st_new_last.st_mtime) { - *st = st_ret_last; -+ zsfree(dir); - return 0; - } - st_new_last = st_tmp; --- -2.17.2 - diff --git a/SOURCES/0003-zsh-5.5.1-parse-error-exit-status.patch b/SOURCES/0003-zsh-5.5.1-parse-error-exit-status.patch deleted file mode 100644 index 6605665..0000000 --- a/SOURCES/0003-zsh-5.5.1-parse-error-exit-status.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 878ebe3c74cee4b9702c9672b87ee56f057e1f02 Mon Sep 17 00:00:00 2001 -From: Peter Stephenson -Date: Thu, 29 Nov 2018 17:54:02 +0000 -Subject: [PATCH] 43854: Set tok to LEXERR on generic parse error. - -Needed by main loop which detects an error this way. - -Upstream-commit: ef20425381e83ebd5a10c2ab270a347018371162 -Signed-off-by: Kamil Dudka ---- - Src/lex.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/Src/lex.c b/Src/lex.c -index 44ad880..c29aaba 100644 ---- a/Src/lex.c -+++ b/Src/lex.c -@@ -1613,6 +1613,7 @@ parsestr(char **s) - zerr("parse error near `%c'", err); - else - zerr("parse error"); -+ tok = LEXERR; - } - } - return err; --- -2.17.2 - diff --git a/SOURCES/0004-zsh-5.5.1-CVE-2019-20044.patch b/SOURCES/0004-zsh-5.5.1-CVE-2019-20044.patch deleted file mode 100644 index 96bfcbb..0000000 --- a/SOURCES/0004-zsh-5.5.1-CVE-2019-20044.patch +++ /dev/null @@ -1,1378 +0,0 @@ -From e6dea148252c9d8cb3de0965f2e558ac13e12f06 Mon Sep 17 00:00:00 2001 -From: Daniel Shahaf -Date: Thu, 26 Dec 2019 11:49:45 +0000 -Subject: [PATCH 1/7] internal: Allow %L in zerrmsg() in non-debug builds, too. - -This will let error messages include long integers. - -Upstream-commit: 81185f4c6106d7ea2f7beaabbec7360c08e400d2 -Signed-off-by: Kamil Dudka ---- - Src/utils.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/Src/utils.c b/Src/utils.c -index 32f6008..2ddc596 100644 ---- a/Src/utils.c -+++ b/Src/utils.c -@@ -325,12 +325,10 @@ zerrmsg(FILE *file, const char *fmt, va_list ap) - nicezputs(s, file); - break; - } --#ifdef DEBUG - case 'L': - lnum = va_arg(ap, long); - fprintf(file, "%ld", lnum); - break; --#endif - case 'd': - num = va_arg(ap, int); - fprintf(file, "%d", num); --- -2.21.1 - - -From 4907caaf15e5a054088e05534c5500679c15b105 Mon Sep 17 00:00:00 2001 -From: dana -Date: Thu, 26 Dec 2019 14:57:07 -0600 -Subject: [PATCH 2/7] unposted: zerrmsg(): Fix macro guard missed in previous - commit - -Upstream-commit: ed21a7b70068b4250a25dcdc5b7213a789b0d0ca -Signed-off-by: Kamil Dudka ---- - Src/utils.c | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/Src/utils.c b/Src/utils.c -index 2ddc596..4a1dcc4 100644 ---- a/Src/utils.c -+++ b/Src/utils.c -@@ -287,9 +287,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap) - { - const char *str; - int num; --#ifdef DEBUG - long lnum; --#endif - #ifdef HAVE_STRERROR_R - #define ERRBUFSIZE (80) - int olderrno; --- -2.21.1 - - -From a6763e5de6eebc5994097fc4d778094e7254589c Mon Sep 17 00:00:00 2001 -From: Sam Foxman -Date: Sun, 22 Dec 2019 17:30:28 -0500 -Subject: [PATCH 3/7] Drop privileges securely - -Upstream-commit: 24e993db62cf146fb76ebcf677a4a7aa3766fc74 -Signed-off-by: Kamil Dudka ---- - Src/options.c | 146 +++++++++++++++++++++++++++++++++++++++++--------- - configure.ac | 4 +- - 2 files changed, 125 insertions(+), 25 deletions(-) - -diff --git a/Src/options.c b/Src/options.c -index 590652e..c9608af 100644 ---- a/Src/options.c -+++ b/Src/options.c -@@ -576,6 +576,7 @@ int - bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - { - int action, optno, match = 0; -+ int retval = 0; - - /* With no arguments or options, display options. */ - if (!*args) { -@@ -603,18 +604,28 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - inittyptab(); - return 1; - } -- if(!(optno = optlookup(*args))) -+ if(!(optno = optlookup(*args))) { - zwarnnam(nam, "no such option: %s", *args); -- else if(dosetopt(optno, action, 0, opts)) -- zwarnnam(nam, "can't change option: %s", *args); -+ retval = 1; -+ } else { -+ retval = !!dosetopt(optno, action, 0, opts); -+ if (retval) { -+ zwarnnam(nam, "can't change option: %s", *args); -+ } -+ } - break; - } else if(**args == 'm') { - match = 1; - } else { -- if (!(optno = optlookupc(**args))) -+ if (!(optno = optlookupc(**args))) { - zwarnnam(nam, "bad option: -%c", **args); -- else if(dosetopt(optno, action, 0, opts)) -- zwarnnam(nam, "can't change option: -%c", **args); -+ retval = 1; -+ } else { -+ retval = !!dosetopt(optno, action, 0, opts); -+ if (retval) { -+ zwarnnam(nam, "can't change option: -%c", **args); -+ } -+ } - } - } - args++; -@@ -624,10 +635,15 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - if (!match) { - /* Not globbing the arguments -- arguments are simply option names. */ - while (*args) { -- if(!(optno = optlookup(*args++))) -+ if(!(optno = optlookup(*args++))) { - zwarnnam(nam, "no such option: %s", args[-1]); -- else if(dosetopt(optno, !isun, 0, opts)) -- zwarnnam(nam, "can't change option: %s", args[-1]); -+ retval = 1; -+ } else { -+ retval = !!dosetopt(optno, !isun, 0, opts); -+ if (retval) { -+ zwarnnam(nam, "can't change option: %s", args[-1]); -+ } -+ } - } - } else { - /* Globbing option (-m) set. */ -@@ -650,7 +666,8 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - tokenize(s); - if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) { - zwarnnam(nam, "bad pattern: %s", *args); -- continue; -+ retval = 1; -+ break; - } - /* Loop over expansions. */ - scanmatchtable(optiontab, pprog, 0, 0, OPT_ALIAS, -@@ -659,7 +676,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - } - } - inittyptab(); -- return 0; -+ return retval; - } - - /* Identify an option name */ -@@ -768,20 +785,101 @@ dosetopt(int optno, int value, int force, char *new_opts) - return -1; - } else if(optno == PRIVILEGED && !value) { - /* unsetting PRIVILEGED causes the shell to make itself unprivileged */ --#ifdef HAVE_SETUID -- setuid(getuid()); -- setgid(getgid()); -- if (setuid(getuid())) { -- zwarn("failed to change user ID: %e", errno); -- return -1; -- } else if (setgid(getgid())) { -- zwarn("failed to change group ID: %e", errno); -- return -1; -- } -+ -+ int skip_setuid = 0; -+ int skip_setgid = 0; -+ -+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -+ int orig_egid = getegid(); -+#endif -+ -+#if defined(HAVE_GETEUID) && defined(HAVE_GETUID) -+ if (geteuid() == getuid()) { -+ skip_setuid = 1; -+ } -+#endif -+ -+#if defined(HAVE_GETEGID) && defined(HAVE_GETGID) -+ if (getegid() == getgid()) { -+ skip_setgid = 1; -+ } -+#endif -+ -+ if (!skip_setgid) { -+ int setgid_err; -+#ifdef HAVE_SETRESGID -+ setgid_err = setresgid(getgid(), getgid(), getgid()); -+#elif defined(HAVE_SETREGID) -+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -+ setgid_err = setregid(getgid(), getgid()); -+#else -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; setregid available, but cannot check if saved gid changed"); -+ return -1; -+#endif -+#else -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid and setregid not available"); -+ return -1; -+#endif -+ if (setgid_err) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno); -+ return -1; -+ } -+ } -+ -+ if (!skip_setuid) { -+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) -+ int orig_euid = geteuid(); -+#endif -+ int setuid_err; -+#if defined(HAVE_GETEUID) && defined(HAVE_INITGROUPS) && defined(HAVE_GETPWUID) -+ if (geteuid() == 0) { -+ struct passwd *pw = getpwuid(getuid()); -+ if (pw == NULL) { -+ zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %d: %e", -+ getuid(), errno); -+ return -1; -+ } -+ if (initgroups(pw->pw_name, pw->pw_gid)) { -+ zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno); -+ return -1; -+ } -+ } -+#endif -+ -+#ifdef HAVE_SETRESUID -+ setuid_err = setresuid(getuid(), getuid(), getuid()); -+#elif defined(HAVE_SETREUID) -+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID) -+ setuid_err = setreuid(getuid(), getuid()); -+#else -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; setreuid available, but cannot check if saved uid changed"); -+ return -1; -+#endif - #else -- zwarn("setuid not available"); -- return -1; --#endif /* not HAVE_SETUID */ -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid and setreuid not available"); -+ return -1; -+#endif -+ if (setuid_err) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno); -+ return -1; -+ } -+#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID) -+ if (getuid() != 0 && !setuid(orig_euid)) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid"); -+ return -1; -+ } -+#endif -+ } -+ -+#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -+ if (getuid() != 0 && !skip_setgid && !setgid(orig_egid)) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the egid"); -+ return -1; -+ } -+#endif -+ - #ifdef JOB_CONTROL - } else if (!force && optno == MONITOR && value) { - if (new_opts[optno] == value) -diff --git a/configure.ac b/configure.ac -index d15a6cd..51cdf89 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1300,7 +1300,9 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ - inet_aton inet_pton inet_ntop \ - getlogin getpwent getpwnam getpwuid getgrgid getgrnam \ - initgroups nis_list \ -- setuid seteuid setreuid setresuid setsid \ -+ getuid setuid seteuid setreuid setresuid setsid \ -+ getgid setgid setegid setregid setresgid \ -+ geteuid getegid \ - memcpy memmove strstr strerror strtoul \ - getrlimit getrusage \ - setlocale \ --- -2.21.1 - - -From 07ec3e46db743ff37fd2bfeafbb4a44ddc7b4aaa Mon Sep 17 00:00:00 2001 -From: Daniel Shahaf -Date: Thu, 26 Dec 2019 09:16:19 +0000 -Subject: [PATCH 4/7] Improve PRIVILEGED fixes -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -- Fix retval handling in bin_setopt() - -- Don't skip_setuid / skip_setgid. It's not our place to optimize away noops - (that might not even _be_ noops; they might change the saved uid…). - -- Remove HAVE_* guard checks around functions that are used unguarded elsewhere. - -- Use bsd-setres_id.c from OpenSSH to provide setresuid() / setresgid() - everywhere, and thus simplify the ifdef soup. Fix some preëxisting - bugs in the macro definitions of setuid() (do we still need that one?). - -- Fix zwarning() format codes for variadic arguments type safety - -- Restored a comment from HEAD - -- Fix failure modes around initgroups() - -- Compared privilege restoration code with OpenSSH's permanently_drop_uid() and - updated as needed - -- Add E01 PRIVILEGED sanity checks - -Upstream-commit: 8250c5c168f07549ed646e6848e6dda118271e23 -Signed-off-by: Kamil Dudka ---- - Src/openssh_bsd_setres_id.c | 129 +++++++++++++++++++++++++++++++ - Src/options.c | 148 ++++++++++++++++-------------------- - Src/zsh.mdd | 3 +- - Src/zsh_system.h | 94 ++++++++++++++++++----- - Test/E01options.ztst | 15 ++++ - configure.ac | 5 +- - 6 files changed, 292 insertions(+), 102 deletions(-) - create mode 100644 Src/openssh_bsd_setres_id.c - -diff --git a/Src/openssh_bsd_setres_id.c b/Src/openssh_bsd_setres_id.c -new file mode 100644 -index 0000000..65e91a4 ---- /dev/null -+++ b/Src/openssh_bsd_setres_id.c -@@ -0,0 +1,129 @@ -+/* -+ * Copyright (c) 2012 Darren Tucker (dtucker at zip com au). -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+/* -+ * openssh_bsd_setres_id.c - setresuid() and setresgid() wrappers -+ * -+ * This file is part of zsh, the Z shell. -+ * -+ * It is based on the file openbsd-compat/bsd-setres_id.c in OpenSSH 7.9p1, -+ * which is subject to the copyright notice above. The zsh modifications are -+ * licensed as follows: -+ * -+ * Copyright (c) 2019 Daniel Shahaf -+ * All rights reserved. -+ * -+ * Permission is hereby granted, without written agreement and without -+ * license or royalty fees, to use, copy, modify, and distribute this -+ * software and to distribute modified versions of this software for any -+ * purpose, provided that the above copyright notice and the following -+ * two paragraphs appear in all copies of this software. -+ * -+ * In no event shall Daniel Shahaf or the Zsh Development Group be liable -+ * to any party for direct, indirect, special, incidental, or consequential -+ * damages arising out of the use of this software and its documentation, -+ * even if Daniel Shahaf and the Zsh Development Group have been advised of -+ * the possibility of such damage. -+ * -+ * Daniel Shahaf and the Zsh Development Group specifically disclaim any -+ * warranties, including, but not limited to, the implied warranties of -+ * merchantability and fitness for a particular purpose. The software -+ * provided hereunder is on an "as is" basis, and Daniel Shahaf and the -+ * Zsh Development Group have no obligation to provide maintenance, -+ * support, updates, enhancements, or modifications. -+ * -+ */ -+ -+ -+#include -+ -+#include -+#include -+#include -+ -+#include "zsh.mdh" -+ -+#if defined(ZSH_IMPLEMENT_SETRESGID) || defined(BROKEN_SETRESGID) -+int -+setresgid(gid_t rgid, gid_t egid, gid_t sgid) -+{ -+ int ret = 0, saved_errno; -+ -+ if (rgid != sgid) { -+ errno = ENOSYS; -+ return -1; -+ } -+#if defined(ZSH_HAVE_NATIVE_SETREGID) && !defined(BROKEN_SETREGID) -+ if (setregid(rgid, egid) < 0) { -+ saved_errno = errno; -+ zwarnnam("setregid", "to gid %L: %e", (long)rgid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+#else -+ if (setegid(egid) < 0) { -+ saved_errno = errno; -+ zwarnnam("setegid", "to gid %L: %e", (long)(unsigned int)egid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+ if (setgid(rgid) < 0) { -+ saved_errno = errno; -+ zwarnnam("setgid", "to gid %L: %e", (long)rgid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+#endif -+ return ret; -+} -+#endif -+ -+#if defined(ZSH_IMPLEMENT_SETRESUID) || defined(BROKEN_SETRESUID) -+int -+setresuid(uid_t ruid, uid_t euid, uid_t suid) -+{ -+ int ret = 0, saved_errno; -+ -+ if (ruid != suid) { -+ errno = ENOSYS; -+ return -1; -+ } -+#if defined(ZSH_HAVE_NATIVE_SETREUID) && !defined(BROKEN_SETREUID) -+ if (setreuid(ruid, euid) < 0) { -+ saved_errno = errno; -+ zwarnnam("setreuid", "to uid %L: %e", (long)ruid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+#else -+ -+# ifndef SETEUID_BREAKS_SETUID -+ if (seteuid(euid) < 0) { -+ saved_errno = errno; -+ zwarnnam("seteuid", "to uid %L: %e", (long)euid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+# endif -+ if (setuid(ruid) < 0) { -+ saved_errno = errno; -+ zwarnnam("setuid", "to uid %L: %e", (long)ruid, errno); -+ errno = saved_errno; -+ ret = -1; -+ } -+#endif -+ return ret; -+} -+#endif -diff --git a/Src/options.c b/Src/options.c -index c9608af..deec560 100644 ---- a/Src/options.c -+++ b/Src/options.c -@@ -606,25 +606,21 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - } - if(!(optno = optlookup(*args))) { - zwarnnam(nam, "no such option: %s", *args); -- retval = 1; -- } else { -- retval = !!dosetopt(optno, action, 0, opts); -- if (retval) { -- zwarnnam(nam, "can't change option: %s", *args); -- } -+ retval |= 1; -+ } else if (dosetopt(optno, action, 0, opts)) { -+ zwarnnam(nam, "can't change option: %s", *args); -+ retval |= 1; - } - break; - } else if(**args == 'm') { - match = 1; - } else { -- if (!(optno = optlookupc(**args))) { -+ if (!(optno = optlookupc(**args))) { - zwarnnam(nam, "bad option: -%c", **args); -- retval = 1; -- } else { -- retval = !!dosetopt(optno, action, 0, opts); -- if (retval) { -- zwarnnam(nam, "can't change option: -%c", **args); -- } -+ retval |= 1; -+ } else if (dosetopt(optno, action, 0, opts)) { -+ zwarnnam(nam, "can't change option: -%c", **args); -+ retval |= 1; - } - } - } -@@ -637,12 +633,10 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - while (*args) { - if(!(optno = optlookup(*args++))) { - zwarnnam(nam, "no such option: %s", args[-1]); -- retval = 1; -- } else { -- retval = !!dosetopt(optno, !isun, 0, opts); -- if (retval) { -- zwarnnam(nam, "can't change option: %s", args[-1]); -- } -+ retval |= 1; -+ } else if (dosetopt(optno, !isun, 0, opts)) { -+ zwarnnam(nam, "can't change option: %s", args[-1]); -+ retval |= 1; - } - } - } else { -@@ -666,7 +660,7 @@ bin_setopt(char *nam, char **args, UNUSED(Options ops), int isun) - tokenize(s); - if (!(pprog = patcompile(s, PAT_HEAPDUP, NULL))) { - zwarnnam(nam, "bad pattern: %s", *args); -- retval = 1; -+ retval |= 1; - break; - } - /* Loop over expansions. */ -@@ -786,100 +780,92 @@ dosetopt(int optno, int value, int force, char *new_opts) - } else if(optno == PRIVILEGED && !value) { - /* unsetting PRIVILEGED causes the shell to make itself unprivileged */ - -- int skip_setuid = 0; -- int skip_setgid = 0; -- --#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -- int orig_egid = getegid(); --#endif -+ /* If set, return -1 so lastval will be non-zero. */ -+ int failed = 0; - --#if defined(HAVE_GETEUID) && defined(HAVE_GETUID) -- if (geteuid() == getuid()) { -- skip_setuid = 1; -- } -+#ifdef HAVE_SETUID -+ const int orig_euid = geteuid(); - #endif -+ const int orig_egid = getegid(); - --#if defined(HAVE_GETEGID) && defined(HAVE_GETGID) -- if (getegid() == getgid()) { -- skip_setgid = 1; -- } --#endif -- -- if (!skip_setgid) { -- int setgid_err; --#ifdef HAVE_SETRESGID -- setgid_err = setresgid(getgid(), getgid(), getgid()); --#elif defined(HAVE_SETREGID) --#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -- setgid_err = setregid(getgid(), getgid()); --#else -- zwarnnam("unsetopt", -- "PRIVILEGED: can't drop privileges; setregid available, but cannot check if saved gid changed"); -+ /* -+ * Set the GID first as if we set the UID to non-privileged it -+ * might be impossible to restore the GID. -+ */ -+ { -+#ifndef HAVE_SETRESGID -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid() and friends not available"); - return -1; --#endif - #else -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid and setregid not available"); -- return -1; --#endif -+ int setgid_err; -+ setgid_err = setresgid(getgid(), getgid(), getgid()); - if (setgid_err) { - zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno); - return -1; - } -+#endif - } - -- if (!skip_setuid) { --#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) -- int orig_euid = geteuid(); --#endif -+ /* Set the UID second. */ -+ { -+#ifndef HAVE_SETRESUID -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid() and friends not available"); -+ return -1; -+#else - int setuid_err; --#if defined(HAVE_GETEUID) && defined(HAVE_INITGROUPS) && defined(HAVE_GETPWUID) -+ -+# ifdef HAVE_INITGROUPS -+ /* Set the supplementary groups list. */ - if (geteuid() == 0) { - struct passwd *pw = getpwuid(getuid()); - if (pw == NULL) { -- zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %d: %e", -- getuid(), errno); -- return -1; -- } -- if (initgroups(pw->pw_name, pw->pw_gid)) { -+ zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %L: %e", -+ (long)getuid(), errno); -+ failed = 1; -+ } else if (initgroups(pw->pw_name, pw->pw_gid)) { - zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno); - return -1; - } -+ } else if (getuid() != 0 && -+ (geteuid() != getuid() || orig_egid != getegid())) { -+ zwarnnam("unsetopt", "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L", -+ (long)geteuid()); -+ failed = 1; - } --#endif -+# else -+ /* initgroups() isn't in POSIX. If it's not available on the system, -+ * we silently skip it. */ -+# endif - --#ifdef HAVE_SETRESUID - setuid_err = setresuid(getuid(), getuid(), getuid()); --#elif defined(HAVE_SETREUID) --#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID) -- setuid_err = setreuid(getuid(), getuid()); --#else -- zwarnnam("unsetopt", -- "PRIVILEGED: can't drop privileges; setreuid available, but cannot check if saved uid changed"); -- return -1; --#endif --#else -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid and setreuid not available"); -- return -1; --#endif - if (setuid_err) { - zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno); - return -1; - } --#if defined(HAVE_GETEUID) && defined(HAVE_SETUID) && defined(HAVE_GETUID) -- if (getuid() != 0 && !setuid(orig_euid)) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid"); -- return -1; -- } - #endif - } - --#if defined(HAVE_GETEGID) && defined(HAVE_SETGID) && defined(HAVE_GETUID) -- if (getuid() != 0 && !skip_setgid && !setgid(orig_egid)) { -+#ifdef HAVE_SETGID -+ if (getuid() != 0 && orig_egid != getegid() && -+ (setgid(orig_egid) != -1 || setegid(orig_egid) != -1)) { - zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the egid"); - return -1; - } - #endif - -+#ifdef HAVE_SETUID -+ if (getuid() != 0 && orig_euid != geteuid() && -+ (setuid(orig_euid) != -1 || seteuid(orig_euid) != -1)) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid"); -+ return -1; -+ } -+#endif -+ -+ if (failed) { -+ /* A warning message has been printed. */ -+ return -1; -+ } -+ - #ifdef JOB_CONTROL - } else if (!force && optno == MONITOR && value) { - if (new_opts[optno] == value) -diff --git a/Src/zsh.mdd b/Src/zsh.mdd -index 324435d..a2590dc 100644 ---- a/Src/zsh.mdd -+++ b/Src/zsh.mdd -@@ -13,7 +13,8 @@ objects="builtin.o compat.o cond.o context.o \ - exec.o glob.o hashtable.o hashnameddir.o \ - hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \ - mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \ --signames.o sort.o string.o subst.o text.o utils.o watch.o" -+signames.o sort.o string.o subst.o text.o utils.o watch.o \ -+openssh_bsd_setres_id.o" - - headers="../config.h zsh_system.h zsh.h sigcount.h signals.h \ - prototypes.h hashtable.h ztype.h" -diff --git a/Src/zsh_system.h b/Src/zsh_system.h -index 5339b49..18fe09b 100644 ---- a/Src/zsh_system.h -+++ b/Src/zsh_system.h -@@ -456,30 +456,90 @@ struct timezone { - # define setpgrp setpgid - #endif - --/* can we set the user/group id of a process */ -+/* compatibility wrappers */ - --#ifndef HAVE_SETUID -+/* Our strategy is as follows: -+ * -+ * - Ensure that either setre[ug]id() or set{e,}[ug]id() is available. -+ * - If setres[ug]id() are missing, provide them in terms of either -+ * setre[ug]id() or set{e,}[ug]id(), whichever is available. -+ * - Provide replacement setre[ug]id() or set{e,}[ug]id() if they are not -+ * available natively. -+ * -+ * There isn't a circular dependency because, right off the bat, we check that -+ * there's an end condition, and #error out otherwise. -+ */ -+#if !defined(HAVE_SETREUID) && !(defined(HAVE_SETEUID) && defined(HAVE_SETUID)) -+ /* -+ * If you run into this error, you have two options: -+ * - Teach zsh how to do the equivalent of setreuid() on your system -+ * - Remove support for PRIVILEGED option, and then remove the #error. -+ */ -+# error "Don't know how to change UID" -+#endif -+#if !defined(HAVE_SETREGID) && !(defined(HAVE_SETEGID) && defined(HAVE_SETGID)) -+ /* See above comment. */ -+# error "Don't know how to change GID" -+#endif -+ -+/* Provide setresuid(). */ -+#ifndef HAVE_SETRESUID -+int setresuid(uid_t, uid_t, uid_t); -+# define HAVE_SETRESUID -+# define ZSH_IMPLEMENT_SETRESUID - # ifdef HAVE_SETREUID --# define setuid(X) setreuid(X,X) --# define setgid(X) setregid(X,X) --# define HAVE_SETUID -+# define ZSH_HAVE_NATIVE_SETREUID - # endif - #endif - --/* can we set the effective user/group id of a process */ -+/* Provide setresgid(). */ -+#ifndef HAVE_SETRESGID -+int setresgid(gid_t, gid_t, gid_t); -+# define HAVE_SETRESGID -+# define ZSH_IMPLEMENT_SETRESGID -+# ifdef HAVE_SETREGID -+# define ZSH_HAVE_NATIVE_SETREGID -+# endif -+#endif - -+/* Provide setreuid(). */ -+#ifndef HAVE_SETREUID -+# define setreuid(X, Y) setresuid((X), (Y), -1) -+# define HAVE_SETREUID -+#endif -+ -+/* Provide setregid(). */ -+#ifndef HAVE_SETREGID -+# define setregid(X, Y) setresgid((X), (Y), -1) -+# define HAVE_SETREGID -+#endif -+ -+/* Provide setuid(). */ -+/* ### TODO: Either remove this (this function has been standard since 1985), -+ * ### or rewrite this without multiply-evaluating the argument */ -+#ifndef HAVE_SETUID -+# define setuid(X) setreuid((X), (X)) -+# define HAVE_SETUID -+#endif -+ -+/* Provide setgid(). */ -+#ifndef HAVE_SETGID -+/* ### TODO: Either remove this (this function has been standard since 1985), -+ * ### or rewrite this without multiply-evaluating the argument */ -+# define setgid(X) setregid((X), (X)) -+# define HAVE_SETGID -+#endif -+ -+/* Provide seteuid(). */ - #ifndef HAVE_SETEUID --# ifdef HAVE_SETREUID --# define seteuid(X) setreuid(-1,X) --# define setegid(X) setregid(-1,X) --# define HAVE_SETEUID --# else --# ifdef HAVE_SETRESUID --# define seteuid(X) setresuid(-1,X,-1) --# define setegid(X) setresgid(-1,X,-1) --# define HAVE_SETEUID --# endif --# endif -+# define seteuid(X) setreuid(-1, (X)) -+# define HAVE_SETEUID -+#endif -+ -+/* Provide setegid(). */ -+#ifndef HAVE_SETEGID -+# define setegid(X) setregid(-1, (X)) -+# define HAVE_SETEGID - #endif - - #ifdef HAVE_SYS_RESOURCE_H -diff --git a/Test/E01options.ztst b/Test/E01options.ztst -index 0f6bb34..c4c3d67 100644 ---- a/Test/E01options.ztst -+++ b/Test/E01options.ztst -@@ -1391,3 +1391,18 @@ F:Regression test for workers/41811 - ?(anon):4: `break' active at end of function scope - ?(anon):4: `break' active at end of function scope - ?(anon):4: `break' active at end of function scope -+ -+# There are further tests for PRIVILEGED in P01privileged.ztst. -+ if [[ -o privileged ]]; then -+ unsetopt privileged -+ fi -+ unsetopt privileged -+0:PRIVILEGED sanity check: unsetting is idempotent -+F:If this test fails at the first unsetopt, refer to P01privileged.ztst. -+ -+ if [[ -o privileged ]]; then -+ (( UID != EUID )) -+ else -+ (( UID == EUID )) -+ fi -+0:PRIVILEGED sanity check: default value is correct -diff --git a/configure.ac b/configure.ac -index 51cdf89..4e30ad1 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1300,9 +1300,8 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \ - inet_aton inet_pton inet_ntop \ - getlogin getpwent getpwnam getpwuid getgrgid getgrnam \ - initgroups nis_list \ -- getuid setuid seteuid setreuid setresuid setsid \ -- getgid setgid setegid setregid setresgid \ -- geteuid getegid \ -+ setuid seteuid setreuid setresuid setsid \ -+ setgid setegid setregid setresgid \ - memcpy memmove strstr strerror strtoul \ - getrlimit getrusage \ - setlocale \ --- -2.21.1 - - -From 6caecc2efb2fa4c708fd27858962ace55d957dce Mon Sep 17 00:00:00 2001 -From: dana -Date: Sun, 29 Dec 2019 02:41:11 +0000 -Subject: [PATCH 5/7] Improve PRIVILEGED fixes (again) - -* Pass RGID instead of passwd GID to initgroups() - -* Clean up #ifdefs, avoid unnecessary checks - -* Flatten conditions - -Upstream-commit: 26d02efa7a9b0a6b32e1a8bbc6aca6c544b94211 -Signed-off-by: Kamil Dudka ---- - Src/options.c | 92 ++++++++++++++++++++++++--------------------------- - 1 file changed, 43 insertions(+), 49 deletions(-) - -diff --git a/Src/options.c b/Src/options.c -index deec560..8599ed3 100644 ---- a/Src/options.c -+++ b/Src/options.c -@@ -780,91 +780,85 @@ dosetopt(int optno, int value, int force, char *new_opts) - } else if(optno == PRIVILEGED && !value) { - /* unsetting PRIVILEGED causes the shell to make itself unprivileged */ - -+/* For simplicity's sake, require both setresgid() and setresuid() up-front. */ -+#if !defined(HAVE_SETRESGID) -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid() and friends not available"); -+ return -1; -+#elif !defined(HAVE_SETRESUID) -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid() and friends not available"); -+ return -1; -+#else - /* If set, return -1 so lastval will be non-zero. */ - int failed = 0; -- --#ifdef HAVE_SETUID - const int orig_euid = geteuid(); --#endif - const int orig_egid = getegid(); - - /* - * Set the GID first as if we set the UID to non-privileged it - * might be impossible to restore the GID. - */ -- { --#ifndef HAVE_SETRESGID -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid() and friends not available"); -+ if (setresgid(getgid(), getgid(), getgid())) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno); - return -1; --#else -- int setgid_err; -- setgid_err = setresgid(getgid(), getgid(), getgid()); -- if (setgid_err) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno); -- return -1; -- } --#endif - } - -- /* Set the UID second. */ -- { --#ifndef HAVE_SETRESUID -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid() and friends not available"); -- return -1; --#else -- int setuid_err; -- - # ifdef HAVE_INITGROUPS -- /* Set the supplementary groups list. */ -- if (geteuid() == 0) { -- struct passwd *pw = getpwuid(getuid()); -- if (pw == NULL) { -- zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %L: %e", -- (long)getuid(), errno); -- failed = 1; -- } else if (initgroups(pw->pw_name, pw->pw_gid)) { -- zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno); -- return -1; -- } -- } else if (getuid() != 0 && -- (geteuid() != getuid() || orig_egid != getegid())) { -- zwarnnam("unsetopt", "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L", -- (long)geteuid()); -+ /* Set the supplementary groups list. -+ * -+ * Note that on macOS, FreeBSD, and possibly some other platforms, -+ * initgroups() resets the EGID to its second argument (see setgroups(2) for -+ * details). This has the potential to leave the EGID in an unexpected -+ * state. However, it seems common in other projects that do this dance to -+ * simply re-use the same GID that's going to become the EGID anyway, in -+ * which case it doesn't matter. That's what we do here. It's therefore -+ * possible, in some probably uncommon cases, that the shell ends up not -+ * having the privileges of the RUID user's primary/passwd group. */ -+ if (geteuid() == 0) { -+ struct passwd *pw = getpwuid(getuid()); -+ if (pw == NULL) { -+ zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %L: %e", -+ (long)getuid(), errno); - failed = 1; -+ /* This may behave strangely in the unlikely event that the same user -+ * name appears with multiple UIDs in the passwd database */ -+ } else if (initgroups(pw->pw_name, getgid())) { -+ zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno); -+ return -1; - } -+ } else if (getuid() != 0 && -+ (geteuid() != getuid() || orig_egid != getegid())) { -+ zwarnnam("unsetopt", "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L", -+ (long)geteuid()); -+ failed = 1; -+ } - # else -- /* initgroups() isn't in POSIX. If it's not available on the system, -- * we silently skip it. */ -+ /* initgroups() isn't in POSIX. If it's not available on the system, -+ * we silently skip it. */ - # endif - -- setuid_err = setresuid(getuid(), getuid(), getuid()); -- if (setuid_err) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno); -- return -1; -- } --#endif -+ /* Set the UID second. */ -+ if (setresuid(getuid(), getuid(), getuid())) { -+ zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno); -+ return -1; - } - --#ifdef HAVE_SETGID - if (getuid() != 0 && orig_egid != getegid() && - (setgid(orig_egid) != -1 || setegid(orig_egid) != -1)) { - zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the egid"); - return -1; - } --#endif - --#ifdef HAVE_SETUID - if (getuid() != 0 && orig_euid != geteuid() && - (setuid(orig_euid) != -1 || seteuid(orig_euid) != -1)) { - zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid"); - return -1; - } --#endif - - if (failed) { - /* A warning message has been printed. */ - return -1; - } -+#endif /* HAVE_SETRESGID && HAVE_SETRESUID */ - - #ifdef JOB_CONTROL - } else if (!force && optno == MONITOR && value) { --- -2.21.1 - - -From 7d224cc6d93933db596ecb4ec78ba5bf48ef2d32 Mon Sep 17 00:00:00 2001 -From: dana -Date: Sun, 29 Dec 2019 02:43:14 +0000 -Subject: [PATCH 6/7] Clean up error-message white space - -Upstream-commit: 4ce66857b71b40a0661df3780ff557f2b0f4cb13 -Signed-off-by: Kamil Dudka ---- - Src/options.c | 30 +++++++++++++++++++++--------- - 1 file changed, 21 insertions(+), 9 deletions(-) - -diff --git a/Src/options.c b/Src/options.c -index 8599ed3..5b972d4 100644 ---- a/Src/options.c -+++ b/Src/options.c -@@ -782,10 +782,12 @@ dosetopt(int optno, int value, int force, char *new_opts) - - /* For simplicity's sake, require both setresgid() and setresuid() up-front. */ - #if !defined(HAVE_SETRESGID) -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresgid() and friends not available"); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; setresgid() and friends not available"); - return -1; - #elif !defined(HAVE_SETRESUID) -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; setresuid() and friends not available"); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; setresuid() and friends not available"); - return -1; - #else - /* If set, return -1 so lastval will be non-zero. */ -@@ -798,7 +800,9 @@ dosetopt(int optno, int value, int force, char *new_opts) - * might be impossible to restore the GID. - */ - if (setresgid(getgid(), getgid(), getgid())) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change group ID: %e", errno); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; failed to change group ID: %e", -+ errno); - return -1; - } - -@@ -816,18 +820,22 @@ dosetopt(int optno, int value, int force, char *new_opts) - if (geteuid() == 0) { - struct passwd *pw = getpwuid(getuid()); - if (pw == NULL) { -- zwarnnam("unsetopt", "can't drop privileges; failed to get user information for uid %L: %e", -+ zwarnnam("unsetopt", -+ "can't drop privileges; failed to get user information for uid %L: %e", - (long)getuid(), errno); - failed = 1; - /* This may behave strangely in the unlikely event that the same user - * name appears with multiple UIDs in the passwd database */ - } else if (initgroups(pw->pw_name, getgid())) { -- zwarnnam("unsetopt", "can't drop privileges; failed to set supplementary group list: %e", errno); -+ zwarnnam("unsetopt", -+ "can't drop privileges; failed to set supplementary group list: %e", -+ errno); - return -1; - } - } else if (getuid() != 0 && - (geteuid() != getuid() || orig_egid != getegid())) { -- zwarnnam("unsetopt", "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L", -+ zwarnnam("unsetopt", -+ "PRIVILEGED: supplementary group list not changed due to lack of permissions: EUID=%L", - (long)geteuid()); - failed = 1; - } -@@ -838,19 +846,23 @@ dosetopt(int optno, int value, int force, char *new_opts) - - /* Set the UID second. */ - if (setresuid(getuid(), getuid(), getuid())) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; failed to change user ID: %e", errno); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; failed to change user ID: %e", -+ errno); - return -1; - } - - if (getuid() != 0 && orig_egid != getegid() && - (setgid(orig_egid) != -1 || setegid(orig_egid) != -1)) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the egid"); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; was able to restore the egid"); - return -1; - } - - if (getuid() != 0 && orig_euid != geteuid() && - (setuid(orig_euid) != -1 || seteuid(orig_euid) != -1)) { -- zwarnnam("unsetopt", "PRIVILEGED: can't drop privileges; was able to restore the euid"); -+ zwarnnam("unsetopt", -+ "PRIVILEGED: can't drop privileges; was able to restore the euid"); - return -1; - } - --- -2.21.1 - - -From a86d3b201352f14bc17c9521baeb5eaa2ad60f1a Mon Sep 17 00:00:00 2001 -From: dana -Date: Sat, 28 Dec 2019 20:45:55 -0600 -Subject: [PATCH 7/7] Add unsetopt/PRIVILEGED tests - -Upstream-commit: b15bd4aa590db8087d1e8f2eb1af2874f5db814d -Signed-off-by: Kamil Dudka ---- - Test/E01options.ztst | 10 +- - Test/P01privileged.ztst | 197 ++++++++++++++++++++++++++++++++++++++++ - Test/README | 1 + - 3 files changed, 207 insertions(+), 1 deletion(-) - create mode 100644 Test/P01privileged.ztst - -diff --git a/Test/E01options.ztst b/Test/E01options.ztst -index c4c3d67..767879a 100644 ---- a/Test/E01options.ztst -+++ b/Test/E01options.ztst -@@ -74,7 +74,6 @@ - # HASH_LIST_ALL ) - # PRINT_EXIT_STATUS haven't worked out what this does yet, although - # Bart suggested a fix. --# PRIVILEGED (similar to GLOBAL_RCS) - # RCS ( " " " " ) - # SH_OPTION_LETTERS even I found this too dull to set up a test for - # SINGLE_COMMAND kills shell -@@ -95,6 +94,15 @@ - - %test - -+ # setopt should move on to the next operation in the face of an error, but -+ # preserve the >0 return code -+ unsetopt aliases -+ setopt not_a_real_option aliases && return 2 -+ print -r - $options[aliases] -+0:setopt error handling -+?(eval):setopt:4: no such option: not_a_real_option -+>on -+ - alias echo='print foo' - unsetopt aliases - # use eval else aliases are all parsed at start -diff --git a/Test/P01privileged.ztst b/Test/P01privileged.ztst -new file mode 100644 -index 0000000..c54112b ---- /dev/null -+++ b/Test/P01privileged.ztst -@@ -0,0 +1,197 @@ -+# This file contains tests related to the PRIVILEGED option. In order to run, -+# it requires that the test process itself have super-user privileges (or that -+# one of the environment variables described below be set). This can be achieved -+# via, e.g., `sudo make check TESTNUM=P`. -+# -+# Optionally, the environment variables ZSH_TEST_UNPRIVILEGED_UID and/or -+# ZSH_TEST_UNPRIVILEGED_GID may be set to UID:EUID or GID:EGID pairs, where the -+# two IDs in each pair are different, non-0 IDs valid on the system being used -+# to run the tests. (The UIDs must both be non-0 to effectively test downgrading -+# of privileges, and they must be non-matching to test auto-enabling of -+# PRIVILEGED and to ensure that disabling PRIVILEGED correctly resets the saved -+# UID. Technically GID 0 is not special, but for simplicity's sake we apply the -+# same requirements here.) -+# -+# If either of the aforementioned environment variables is not set, the test -+# script will try to pick the first two >0 IDs from the passwd/group databases -+# on the current system. -+# -+# If either variable is set, the tests will run, but they will likely fail -+# without super-user privileges. -+ -+%prep -+ -+ # Mind your empty lines here. The logic in this %prep section is somewhat -+ # complex compared to most others; to avoid lots of nested/duplicated -+ # conditions we need to make sure that this all gets executed as a single -+ # function from which we can return early -+ [[ $EUID == 0 || -n $ZSH_TEST_UNPRIVILEGED_UID$ZSH_TEST_UNPRIVILEGED_GID ]] || { -+ ZTST_unimplemented='PRIVILEGED tests require super-user privileges (or env var)' -+ return 1 -+ } -+ (( $+commands[perl] )) || { # @todo Eliminate this dependency with a C wrapper? -+ ZTST_unimplemented='PRIVILEGED tests require Perl' -+ return 1 -+ } -+ grep -qE '#define HAVE_SETRES?UID' $ZTST_testdir/../config.h || { -+ ZTST_unimplemented='PRIVILEGED tests require setreuid()/setresuid()' -+ return 1 -+ } -+ # -+ ruid= euid= rgid= egid= -+ # -+ if [[ -n $ZSH_TEST_UNPRIVILEGED_UID ]]; then -+ ruid=${ZSH_TEST_UNPRIVILEGED_UID%%:*} -+ euid=${ZSH_TEST_UNPRIVILEGED_UID##*:} -+ else -+ print -ru$ZTST_fd 'Selecting unprivileged UID:EUID pair automatically' -+ local tmp=$( getent passwd 2> /dev/null || < /etc/passwd ) -+ # Note: Some awks require -v and its argument to be separate -+ ruid=$( awk -F: '$3 > 0 { print $3; exit; }' <<< $tmp ) -+ euid=$( awk -F: -v u=$ruid '$3 > u { print $3; exit; }' <<< $tmp ) -+ fi -+ # -+ if [[ -n $ZSH_TEST_UNPRIVILEGED_GID ]]; then -+ rgid=${ZSH_TEST_UNPRIVILEGED_GID%%:*} -+ egid=${ZSH_TEST_UNPRIVILEGED_GID##*:} -+ else -+ print -ru$ZTST_fd 'Selecting unprivileged GID:EGID pair automatically' -+ local tmp=$( getent group 2> /dev/null || < /etc/group ) -+ # Note: Some awks require -v and its argument to be separate -+ rgid=$( awk -F: '$3 > 0 { print $3; exit; }' <<< $tmp ) -+ egid=$( awk -F: -v g=$rgid '$3 > g { print $3; exit; }' <<< $tmp ) -+ fi -+ # -+ [[ $ruid/$euid == <1->/<1-> && $ruid != $euid ]] || ruid= euid= -+ [[ $rgid/$egid == <1->/<1-> && $rgid != $egid ]] || rgid= egid= -+ # -+ [[ -n $ruid && -n $euid ]] || { -+ ZTST_unimplemented='PRIVILEGED tests require unprivileged UID:EUID' -+ return 1 -+ } -+ [[ -n $rgid || -n $egid ]] || { -+ ZTST_unimplemented='PRIVILEGED tests require unprivileged GID:EGID' -+ return 1 -+ } -+ # -+ print -ru$ZTST_fd \ -+ "Using unprivileged UID $ruid, EUID $euid, GID $rgid, EGID $egid" -+ # -+ # Execute process with specified UID and EUID -+ # $1 => Real UID -+ # $2 => Effective UID -+ # $3 => Real GID -+ # $4 => Effective GID -+ # $5 ... => Command + args to execute (must NOT be a shell command string) -+ re_exec() { -+ perl -e ' -+ die("re_exec: not enough arguments") unless (@ARGV >= 5); -+ my ($ruid, $euid, $rgid, $egid, @cmd) = @ARGV; -+ foreach my $id ($ruid, $euid, $rgid, $egid) { -+ die("re_exec: invalid ID: $id") unless ($id =~ /^(-1|\d+)$/a); -+ } -+ $< = 0 + $ruid if ($ruid >= 0); -+ $> = 0 + $euid if ($euid >= 0); -+ $( = 0 + $rgid if ($rgid >= 0); -+ $) = 0 + $egid if ($egid >= 0); -+ exec(@cmd); -+ die("re_exec: exec failed: $!"); -+ ' -- "$@" -+ } -+ # -+ # Convenience wrapper for re_exec to call `zsh -c` -+ # -* ... => (optional) Command-line options to zsh -+ # $1 => Real UID -+ # $2 => Effective UID -+ # $3 => Real GID -+ # $4 => Effective GID -+ # $5 ... => zsh command string; multiple strings are joined by \n -+ re_zsh() { -+ local -a opts -+ while [[ $1 == -[A-Za-z-]* ]]; do -+ opts+=( $1 ) -+ shift -+ done -+ re_exec "$1" "$2" "$3" "$4" $ZTST_exe $opts -fc \ -+ "MODULE_PATH=${(q)MODULE_PATH}; ${(F)@[5,-1]}" -+ } -+ # -+ # Return one or more random unused UIDs -+ # $1 ... => Names of parameters to store UIDs in -+ get_unused_uid() { -+ while (( $# )); do -+ local i_=0 uid_= -+ until [[ -n $uid_ ]]; do -+ (( ++i_ > 99 )) && return 1 -+ uid_=$RANDOM -+ id $uid_ &> /dev/null || break -+ uid_= -+ done -+ : ${(P)1::=$uid_} -+ shift -+ done -+ } -+ -+%test -+ -+ re_zsh $ruid $ruid -1 -1 'echo $UID/$EUID $options[privileged]' -+ re_zsh $euid $euid -1 -1 'echo $UID/$EUID $options[privileged]' -+ re_zsh $ruid $euid -1 -1 'echo $UID/$EUID $options[privileged]' -+0q:PRIVILEGED automatically enabled when RUID != EUID -+>$ruid/$ruid off -+>$euid/$euid off -+>$ruid/$euid on -+ -+ re_zsh -1 -1 $rgid $rgid 'echo $GID/$EGID $options[privileged]' -+ re_zsh -1 -1 $egid $egid 'echo $GID/$EGID $options[privileged]' -+ re_zsh -1 -1 $rgid $egid 'echo $GID/$EGID $options[privileged]' -+0q:PRIVILEGED automatically enabled when RGID != EGID -+>$rgid/$rgid off -+>$egid/$egid off -+>$rgid/$egid on -+ -+ re_zsh $ruid $euid -1 -1 'unsetopt privileged; echo $UID/$EUID' -+0q:EUID set to RUID after disabling PRIVILEGED -+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed * -+*?zsh:unsetopt:1: can't change option: privileged -+>$ruid/$ruid -+ -+ re_zsh 0 $euid -1 -1 'unsetopt privileged && echo $UID/$EUID' -+0:RUID/EUID set to 0/0 when privileged after disabling PRIVILEGED -+>0/0 -+ -+ re_zsh $ruid $euid -1 -1 "unsetopt privileged; UID=$euid" || -+ re_zsh $ruid $euid -1 -1 "unsetopt privileged; EUID=$euid" -+1:not possible to regain EUID when unprivileged after disabling PRIVILEGED -+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed * -+*?zsh:unsetopt:1: can't change option: privileged -+*?zsh:1: failed to change user ID: * -+*?zsh:unsetopt:1: PRIVILEGED: supplementary group list not changed * -+*?zsh:unsetopt:1: can't change option: privileged -+*?zsh:1: failed to change effective user ID: * -+ -+ re_zsh -1 -1 $rgid $egid 'unsetopt privileged && echo $GID/$EGID' -+0q:EGID set to RGID after disabling PRIVILEGED -+>$rgid/$rgid -+ -+# This test also confirms that we can't revert to the original EUID's primary -+# GID, which initgroups() may reset the EGID to on some systems -+ re_zsh $ruid 0 $rgid 0 'unsetopt privileged; GID=0' || -+ re_zsh $ruid 0 $rgid 0 'unsetopt privileged; EGID=0' -+1:not possible to regain EGID when unprivileged after disabling PRIVILEGED -+*?zsh:1: failed to change group ID: * -+*?zsh:1: failed to change effective group ID: * -+ -+ local rruid -+ grep -qF '#define HAVE_INITGROUPS' $ZTST_testdir/../config.h || { -+ ZTST_skip='initgroups() not available' -+ return 1 -+ } -+ get_unused_uid rruid || { -+ ZTST_skip="Can't get unused UID" -+ return 1 -+ } -+ re_zsh $rruid 0 -1 -1 'unsetopt privileged' -+1:getpwuid() fails with non-existent RUID and 0 EUID -+*?zsh:unsetopt:1: can't drop privileges; failed to get user information * -+*?zsh:unsetopt:1: can't change option: privileged -diff --git a/Test/README b/Test/README -index d012277..726d68e 100644 ---- a/Test/README -+++ b/Test/README -@@ -6,6 +6,7 @@ scripts names: - C: shell commands with special syntax - D: substititution - E: options -+ P: privileged (needs super-user privileges) - V: modules - W: builtin interactive commands and constructs - X: line editing --- -2.21.1 - diff --git a/SOURCES/0005-zsh-5.5.1-CVE-2021-45444.patch b/SOURCES/0005-zsh-5.5.1-CVE-2021-45444.patch deleted file mode 100644 index 5de9e72..0000000 --- a/SOURCES/0005-zsh-5.5.1-CVE-2021-45444.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 9ce87af4ced4e21258e6003f1fb65b05ca5a7d14 Mon Sep 17 00:00:00 2001 -From: Oliver Kiddle -Date: Wed, 15 Dec 2021 01:56:40 +0100 -Subject: [PATCH] security/41: Don't perform PROMPT_SUBST evaluation on %F/%K - arguments - -Mitigates CVE-2021-45444 - -Upstream-commit: c187154f47697cdbf822c2f9d714d570ed4a0fd1 -Signed-off-by: Kamil Dudka ---- - Src/prompt.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/Src/prompt.c b/Src/prompt.c -index 95da525..1368f8e 100644 ---- a/Src/prompt.c -+++ b/Src/prompt.c -@@ -244,6 +244,12 @@ parsecolorchar(int arg, int is_fg) - bv->fm += 2; /* skip over F{ */ - if ((ep = strchr(bv->fm, '}'))) { - char oc = *ep, *col, *coll; -+ int ops = opts[PROMPTSUBST], opb = opts[PROMPTBANG]; -+ int opp = opts[PROMPTPERCENT]; -+ -+ opts[PROMPTPERCENT] = 1; -+ opts[PROMPTSUBST] = opts[PROMPTBANG] = 0; -+ - *ep = '\0'; - /* expand the contents of the argument so you can use - * %v for example */ -@@ -252,6 +258,10 @@ parsecolorchar(int arg, int is_fg) - arg = match_colour((const char **)&coll, is_fg, 0); - free(col); - bv->fm = ep; -+ -+ opts[PROMPTSUBST] = ops; -+ opts[PROMPTBANG] = opb; -+ opts[PROMPTPERCENT] = opp; - } else { - arg = match_colour((const char **)&bv->fm, is_fg, 0); - if (*bv->fm != '}') --- -2.34.1 - diff --git a/SOURCES/0006-zsh-5.5.1-fix-wait.patch b/SOURCES/0006-zsh-5.5.1-fix-wait.patch deleted file mode 100644 index f89073e..0000000 --- a/SOURCES/0006-zsh-5.5.1-fix-wait.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 6af0b07cc7950159129156cb85ef3f72fdd828cc Mon Sep 17 00:00:00 2001 -From: Peter Stephenson -Date: Sat, 3 Aug 2019 19:48:18 +0100 -Subject: [PATCH] 44635: Don't apply STAT_NOPRINT to backgrounded jobs - -Upstream-commit: e0d063a2ade821baf570eb300d4be93692b494f8 -Signed-off-by: Kamil Dudka ---- - Src/exec.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/Src/exec.c b/Src/exec.c -index 8045db2..da089d6 100644 ---- a/Src/exec.c -+++ b/Src/exec.c -@@ -1666,7 +1666,8 @@ execpline(Estate state, wordcode slcode, int how, int last1) - - lastwj = thisjob = newjob; - -- if (list_pipe || (pline_level && !(how & Z_TIMED))) -+ if (list_pipe || (pline_level && !(how & Z_TIMED) && -+ !(jn->stat & STAT_NOSTTY))) - jn->stat |= STAT_NOPRINT; - - if (nowait) { --- -2.34.1 - diff --git a/dotzprofile b/dotzprofile new file mode 100644 index 0000000..9203f7e --- /dev/null +++ b/dotzprofile @@ -0,0 +1,12 @@ +# this file is installed as ~/.zprofile for newly created users + +# prepend ~/.local/bin and ~/bin to $PATH unless it is already there +if ! [[ "$PATH" =~ "$HOME/bin" ]] +then + PATH="$HOME/bin:$PATH" +fi +if ! [[ "$PATH" =~ "$HOME/.local/bin:" ]] +then + PATH="$HOME/.local/bin:$PATH" +fi +export PATH diff --git a/SOURCES/dotzshrc b/dotzshrc similarity index 100% rename from SOURCES/dotzshrc rename to dotzshrc diff --git a/sources b/sources new file mode 100644 index 0000000..fd1f5c6 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (zsh-5.9.tar.xz) = d9138b7f379ad942a5f46819d2dd52d31f3a1129f2a0d1b53d4c5cd43c318b60396da6d37c57c477b8e958fb750209aca0ae93f8c9dd42ac958de006a0ff067e diff --git a/SOURCES/zlogin.rhs b/zlogin.rhs similarity index 100% rename from SOURCES/zlogin.rhs rename to zlogin.rhs diff --git a/SOURCES/zlogout.rhs b/zlogout.rhs similarity index 100% rename from SOURCES/zlogout.rhs rename to zlogout.rhs diff --git a/SOURCES/zprofile.rhs b/zprofile.rhs similarity index 90% rename from SOURCES/zprofile.rhs rename to zprofile.rhs index 03d316f..5e21475 100644 --- a/SOURCES/zprofile.rhs +++ b/zprofile.rhs @@ -2,9 +2,6 @@ # /etc/zprofile and ~/.zprofile are run for login shells # -PATH="$PATH:$HOME/bin" -export PATH - _src_etc_profile() { # Make /etc/profile happier, and have possible ~/.zshenv options like diff --git a/SPECS/zsh.spec b/zsh.spec similarity index 71% rename from SPECS/zsh.spec rename to zsh.spec index 0efe556..39cbce5 100644 --- a/SPECS/zsh.spec +++ b/zsh.spec @@ -1,8 +1,8 @@ Summary: Powerful interactive shell Name: zsh -Version: 5.5.1 -Release: 10%{?dist} -License: MIT +Version: 5.9 +Release: 15%{?dist} +License: MIT-Modern-Variant AND ISC AND GPL-2.0-only URL: http://zsh.sourceforge.net/ Source0: https://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.xz Source1: zlogin.rhs @@ -11,38 +11,39 @@ Source3: zprofile.rhs Source4: zshrc.rhs Source5: zshenv.rhs Source6: dotzshrc +Source7: dotzprofile -# fix two security issues in shebang line parsing (CVE-2018-0502 CVE-2018-13259) -Patch1: 0001-zsh-5.5.1-CVE-2018-0502-CVE-2018-13259.patch - -# fix programming mistakes detected by static analysis (#1602743) -Patch2: 0002-zsh-5.5.1-static-analysis.patch - -# return non-zero exit status on nested parse error (#1654989) -Patch3: 0003-zsh-5.5.1-parse-error-exit-status.patch - -# drop privileges securely when unsetting PRIVILEGED option (CVE-2019-20044) -Patch4: 0004-zsh-5.5.1-CVE-2019-20044.patch - -# do not perform PROMPT_SUBST evaluation on %F/%K arguments (CVE-2021-45444) -Patch5: 0005-zsh-5.5.1-CVE-2021-45444.patch - -# make zsh wait built-in wait properly for all active child processes (#2070342) -Patch6: 0006-zsh-5.5.1-fix-wait.patch +# do not use egrep in tests to make them pass again +Patch1: 0001-zsh-5.9-do-not-use-egrep-in-tests.patch +# Upstream commit ab4d62eb975a4c4c51dd35822665050e2ddc6918 +Patch2: 0002-zsh-Use-int-main-in-test-c-codes.patch +# upstream commit a84fdd7c8f77935ecce99ff2b0bdba738821ed79 +Patch3: 0003-zsh-fix-module-loading-problem-with-full-RELRO.patch +# upstream commit 1b421e4978440234fb73117c8505dad1ccc68d46 +Patch4: 0004-zsh-enable-PCRE-locale-switching.patch +# upstream commit b62e911341c8ec7446378b477c47da4256053dc0 and 10bdbd8b5b0b43445aff23dcd412f25cf6aa328a +Patch5: 0005-zsh-port-to-pcre2.patch +# upstream commit ecd3f9c9506c7720dc6c0833dc5d5eb00e4459c4 +Patch6: 0006-zsh-support-texinfo-7.0.patch +# upstream commit 4c89849c98172c951a9def3690e8647dae76308f +Patch7: 0007-zsh-configure-c99.patch +# upstream commit d3edf318306e37d2d96c4e4ea442d10207722e94 +Patch8: 0008-zsh-deletefilelist-segfault.patch BuildRequires: autoconf BuildRequires: coreutils BuildRequires: gawk BuildRequires: gcc BuildRequires: gdbm-devel +BuildRequires: glibc-langpack-ja BuildRequires: libcap-devel +BuildRequires: make BuildRequires: ncurses-devel -BuildRequires: pcre-devel +BuildRequires: pcre2-devel BuildRequires: sed BuildRequires: texi2html BuildRequires: texinfo -Requires(post): info grep -Requires(preun): info +Requires(post): grep Requires(postun): coreutils grep # the hostname package is not available on RHEL-6 @@ -88,8 +89,8 @@ sed -e 's|^\.NOTPARALLEL|#.NOTPARALLEL|' -i 'Config/defs.mk.in' # make build of run-time loadable modules work again (#1535422) %undefine _strict_symbol_defs_build -# make loading of module's dependencies work again (#1277996) -export LIBLDFLAGS='-z lazy' +# avoid build failure in case we have working ypcat (#1687574) +export zsh_cv_sys_nis='no' %configure \ --enable-etcdir=%{_sysconfdir} \ @@ -101,10 +102,13 @@ export LIBLDFLAGS='-z lazy' make -C Src headers make -C Src -f Makemod zsh{path,xmod}s.h version.h -make %{?_smp_mflags} all html +%make_build all html %check -# Run the testsuite +# avoid unnecessary failure of the test-suite in case ${RPS1} is set +unset RPS1 + +# run the test-suite make check %install @@ -125,11 +129,12 @@ done mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/skel install -m 644 %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir}/skel/.zshrc +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_sysconfdir}/skel/.zprofile # This is just here to shut up rpmlint, and is very annoying. # Note that we can't chmod everything as then rpmlint will complain about # those without a she-bang line. -for i in checkmail harden run-help zcalc zkbd; do +for i in checkmail harden run-help test-repo-git-rebase-{apply,merge} zcalc zkbd; do sed -i -e 's!/usr/local/bin/zsh!%{_bindir}/zsh!' \ $RPM_BUILD_ROOT%{_datadir}/zsh/%{version}/functions/$i chmod +x $RPM_BUILD_ROOT%{_datadir}/zsh/%{version}/functions/$i @@ -147,22 +152,6 @@ if [ "$1" = 1 ]; then fi fi -if [ -f %{_infodir}/zsh.info.gz ]; then -# This is needed so that --excludedocs works. -/sbin/install-info %{_infodir}/zsh.info.gz %{_infodir}/dir \ - --entry="* zsh: (zsh). An enhanced bourne shell." -fi - - -%preun -if [ "$1" = 0 ] ; then - if [ -f %{_infodir}/zsh.info.gz ]; then - # This is needed so that --excludedocs works. - /sbin/install-info --delete %{_infodir}/zsh.info.gz %{_infodir}/dir \ - --entry="* zsh: (zsh). An enhanced bourne shell." - fi -fi - %postun if [ "$1" = 0 ] && [ -f %{_sysconfdir}/shells ] ; then sed -i '\!^%{_bindir}/%{name}$!d' %{_sysconfdir}/shells @@ -185,32 +174,122 @@ fi %doc Doc/*.html %changelog -* Fri Apr 01 2022 Kamil Dudka - 5.5.1-10 -- make zsh wait built-in wait properly for all active child processes (#2070342) +* Tue Oct 29 2024 Troy Dawson - 5.9-15 +- Bump release for October 2024 mass rebuild: + Resolves: RHEL-64018 -* Tue Feb 22 2022 Kamil Dudka - 5.5.1-9 -- do not perform PROMPT_SUBST evaluation on %F/%K arguments (CVE-2021-45444) +* Mon Jun 24 2024 Troy Dawson - 5.9-14 +- Bump release for June 2024 mass rebuild -* Tue Mar 03 2020 Kamil Dudka - 5.5.1-8 -- improve printing of error messages introduced by the fix of CVE-2019-20044 +* Sat Jan 27 2024 Fedora Release Engineering - 5.9-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild -* Mon Feb 24 2020 Kamil Dudka - 5.5.1-7 -- drop privileges securely when unsetting PRIVILEGED option (CVE-2019-20044) +* Wed Jan 17 2024 Lukáš Zaoral - 5.9-12 +- fix segfault in delerefilelist (rhbz#2245462) -* Mon Dec 17 2018 Kamil Dudka - 5.5.1-6 +* Fri Dec 8 2023 Florian Weimer - 5.9-11 +- Fix C compatibility issue in the configure script + +* Tue Nov 21 2023 Lukáš Zaoral - 5.9-10 +- fix FTBFS caused by texinfo 7.1 +- fix build of the PCRE module + +* Mon Aug 21 2023 Lukáš Zaoral - 5.9-9 +- port to PCRE 2 (rhbz#1938979) + +* Sat Jul 22 2023 Fedora Release Engineering - 5.9-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Thu Jul 13 2023 Lukáš Zaoral - 5.9-7 +- Make zsh/{tcp,zftp} compatible with full RELRO (rhbz#2212160) + +* Wed May 17 2023 David Cantrell - 5.9-6 +- Update the License tag to use SPDX identifiers + +* Sat Jan 21 2023 Fedora Release Engineering - 5.9-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Jan 13 2023 Timm Bäder - 5.9-4 +- use 'int main()' in test C-codes in configure + +* Mon Jan 09 2023 Kamil Dudka - 5.9-3 +- do not use egrep in tests to make them pass again + +* Sat Jul 23 2022 Fedora Release Engineering - 5.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Sun May 15 2022 Kamil Dudka - 5.9-1 +- update to latest upstream release + +* Sun Feb 13 2022 Kamil Dudka - 5.8.1-1 +- update to latest upstream release (fixes CVE-2021-45444) + +* Sat Jan 22 2022 Fedora Release Engineering - 5.8-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Tue Jan 04 2022 Kamil Dudka - 5.8-8 +- prepend ~/.local/bin and ~/bin to $PATH for newly created users (#1900809) + +* Thu Nov 25 2021 Debarshi Ray - 5.8-7 +- Overwrite PROMPT only if it's set to the built-in default (#2026749) + +* Fri Jul 23 2021 Fedora Release Engineering - 5.8-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Thu Mar 25 2021 Kamil Dudka - 5.8-5 +- complete file arguments after rpmbuild -r/-b/-t + +* Thu Jan 28 2021 Fedora Release Engineering - 5.8-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jul 29 2020 Fedora Release Engineering - 5.8-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 14 2020 Tom Stellard - 5.8-2 +- Use make macros +- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro + +* Mon Feb 24 2020 Kamil Dudka - 5.8-1 +- update to latest upstream release + +* Fri Jan 31 2020 Fedora Release Engineering - 5.7.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Jul 26 2019 Kamil Dudka - 5.7.1-4 +- make failed searches of history in Zle robust (#1722703) + +* Tue Mar 12 2019 Kamil Dudka - 5.7.1-3 +- avoid build failure in case we have working ypcat (#1687574) + +* Fri Mar 8 2019 Tim Landscheidt - 5.7.1-2 +- Remove obsolete requirements for %%post/%%preun scriptlets + +* Mon Feb 04 2019 Kamil Dudka - 5.7.1-1 +- update to latest upstream release + +* Sun Feb 03 2019 Fedora Release Engineering - 5.7-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Mon Jan 28 2019 Jason L Tibbitts III - 5.7-1 +- Update to latest upstream release. + +* Fri Nov 30 2018 Kamil Dudka - 5.6.2-3 - return non-zero exit status on nested parse error (#1654989) -* Mon Nov 12 2018 Kamil Dudka - 5.5.1-5 -- fix programming mistakes detected by static analysis (#1602743) +* Mon Nov 12 2018 Kamil Dudka - 5.6.2-2 +- fix programming mistakes detected by static analysis -* Thu Oct 11 2018 Kamil Dudka - 5.5.1-4 -- fix two security issues in shebang line parsing (CVE-2018-0502 CVE-2018-13259) +* Fri Sep 14 2018 Kamil Dudka - 5.6.2-1 +- update to latest upstream release -* Mon Jul 30 2018 Florian Weimer - 5.5.1-3 -- Rebuild with fixed binutils +* Mon Sep 10 2018 Kamil Dudka - 5.6.1-1 +- update to latest upstream release -* Wed Jul 25 2018 Petr Kubat - 5.5.1-2 -- Rebuilt for gdbm +* Tue Sep 04 2018 Kamil Dudka - 5.6-1 +- update to latest upstream release (fixes CVE-2018-0502 and CVE-2018-13259) + +* Sat Jul 14 2018 Fedora Release Engineering - 5.5.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild * Tue Apr 17 2018 Kamil Dudka - 5.5.1-1 - update to latest upstream release diff --git a/SOURCES/zshenv.rhs b/zshenv.rhs similarity index 100% rename from SOURCES/zshenv.rhs rename to zshenv.rhs diff --git a/SOURCES/zshrc.rhs b/zshrc.rhs similarity index 93% rename from SOURCES/zshrc.rhs rename to zshrc.rhs index 5b3b92a..82dc213 100644 --- a/SOURCES/zshrc.rhs +++ b/zshrc.rhs @@ -8,7 +8,7 @@ #setenv() { export $1=$2 } # csh compatibility # Set prompts -PROMPT='[%n@%m]%~%# ' # default prompt +[[ "$PROMPT" = "%m%# " ]] && PROMPT='[%n@%m]%~%# ' # default prompt #RPROMPT=' %~' # prompt for right side of screen # bindkey -v # vi key bindings