Hello community,

here is the log from the commit of package zsh for openSUSE:Factory checked in 
at 2020-02-20 14:53:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/zsh (Old)
 and      /work/SRC/openSUSE:Factory/.zsh.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "zsh"

Thu Feb 20 14:53:48 2020 rev:89 rq:774851 version:5.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/zsh/zsh.changes  2020-02-15 22:23:28.383246555 
+0100
+++ /work/SRC/openSUSE:Factory/.zsh.new.26092/zsh.changes       2020-02-20 
14:53:55.814117341 +0100
@@ -1,0 +2,6 @@
+Mon Feb 17 05:18:47 UTC 2020 - Ismail Dönmez <[email protected]>
+
+- Update to version 5.8
+  * Fixes CVE-2019-20044 bsc#1163882
+
+-------------------------------------------------------------------

Old:
----
  zsh-5.7.1-test-3.tar.xz
  zsh-5.7.1-test-3.tar.xz.asc

New:
----
  zsh-5.8.tar.xz
  zsh-5.8.tar.xz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ zsh.spec ++++++
--- /var/tmp/diff_new_pack.KBH2PU/_old  2020-02-20 14:53:56.666119013 +0100
+++ /var/tmp/diff_new_pack.KBH2PU/_new  2020-02-20 14:53:56.666119013 +0100
@@ -16,9 +16,6 @@
 #
 
 
-# Only for -test builds
-%define _version 5.7.1-test-3
-
 %if 0%{?rhel_version} || 0%{?centos_version} || 0%{?fedora_version}
 %if 0%{?rhel_version} >= 700 || 0%{?centos_version} >= 700
 %global __requires_exclude ^/bin/zsh$
@@ -28,14 +25,14 @@
 BuildRequires:  texinfo
 %endif
 Name:           zsh
-Version:        5.8~pre3
+Version:        5.8
 Release:        0%{?dist}
 Summary:        Shell with comprehensive completion
 License:        MIT
 Group:          System/Shells
 URL:            http://www.zsh.org
-Source0:        
https://downloads.sourceforge.net/project/zsh/zsh-test/%{_version}/zsh-%{_version}.tar.xz
-Source1:        
https://downloads.sourceforge.net/project/zsh/zsh-test/%{_version}/zsh-%{_version}.tar.xz.asc
+Source0:        
https://downloads.sourceforge.net/project/zsh/zsh/%{version}/zsh-%{version}.tar.xz
+Source1:        
https://downloads.sourceforge.net/project/zsh/zsh/%{version}/zsh-%{version}.tar.xz.asc
 Source2:        %{name}.keyring
 Source3:        zshrc
 Source4:        zshenv
@@ -94,7 +91,7 @@
 This package contains the Zsh manual in HTML format.
 
 %prep
-%setup -q -n %{name}-%{_version}
+%setup -q
 %if 0%{?suse_version}
 %patch1 -p1
 %endif

++++++ zsh-5.7.1-test-3.tar.xz -> zsh-5.8.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/ChangeLog new/zsh-5.8/ChangeLog
--- old/zsh-5.7.1-test-3/ChangeLog      2020-02-06 20:57:35.000000000 +0100
+++ new/zsh-5.8/ChangeLog       2020-02-14 23:11:10.000000000 +0100
@@ -1,3 +1,28 @@
+2020-02-14  dana  <[email protected]>
+
+       * unposted: Config/version.mk: Update for 5.8
+
+       * Sam Foxman, Daniel Shahaf, dana: CVE-2019-20044: NEWS,
+       README, Src/openssh_bsd_setres_id.c, Src/options.c, Src/zsh.mdd,
+       Src/zsh_system.h, Test/E01options.ztst, Test/P01privileged.ztst,
+       Test/README, configure.ac: Fix insecure dropping of privileges
+       when unsetting PRIVILEGED option
+
+       * unposted: Test/V01zmodload.ztst: Fix failing test from
+       workers/45385
+
+       * 45423 (tweaked): Completion/Unix/Command/_su: Improve arg
+       handling, shell look-ups
+
+2020-02-07  dana  <[email protected]>
+
+       * unposted: Completion/Unix/Command/_zip: Recognise '--'
+
+2020-02-06  Daniel Shahaf  <[email protected]>
+
+       * 45385: Test/V01zmodload.ztst: Add a test for 'zmodload -Fa'
+       preemptively disabling ("blacklisting"?) features.
+
 2020-02-06  dana  <[email protected]>
 
        * unposted: Config/version.mk: Update for 5.7.1-test-3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Completion/Unix/Command/_su 
new/zsh-5.8/Completion/Unix/Command/_su
--- old/zsh-5.7.1-test-3/Completion/Unix/Command/_su    2017-12-04 
15:09:35.000000000 +0100
+++ new/zsh-5.8/Completion/Unix/Command/_su     2020-02-14 17:15:11.000000000 
+0100
@@ -9,36 +9,44 @@
 (( $words[(i)-(l|-login)] < CURRENT )) || args=( '-[use a login shell]' )
 case $OSTYPE in
   linux*)
+    # Some of these options only apply to util-linux, not shadow-utils
     args=( -S $args
-      '(-c --command --session-command *)'{-c,--command=}'[pass command to 
shell]:command string:_cmdstring'
+      '(-c --command --session-command *)'{-c+,--command=}'[pass command to 
shell]:command string:_cmdstring'
       "(-c --command *)--session-command=[pass command to shell and don't 
create a new session]:command string:_cmdstring"
       '(--fast -f)'{-f,--fast}'[pass -f to shell]'
       '(-l --login -m -p --preserve-environment)'{-l,--login}'[use a login 
shell]'
       '(-l --login -m -p 
--preserve-environment)'{-m,-p,--preserve-environment}"[don't reset 
environment]"
-      '(-s --shell)'{-s,--shell=}'[run the specified shell]:shell:->shells'
+      '(-s --shell)'{-s+,--shell=}'[run the specified shell]:shell:->shells'
       '(-)--help[display help information]'
       '(-)--version[display version information]'
     )
-    (( EUID )) || args+=(
-      '(-g --group)'{-g,--group=}'[specify primary group]:group:_groups'
-      \*{-G,--supp-group=}'[specify supplemental group]:group:_groups'
+    (( $#_comp_priv_prefix || EUID == 0 )) && args+=(
+      '(-g --group)'{-g+,--group=}'[specify primary group]:group:_groups'
+      \*{-G+,--supp-group=}'[specify supplemental group]:group:_groups'
     )
     first="(--help --version)${first#???}"
   ;;
   *bsd*|darwin*|dragonfly*)
     args+=(
-      '-c[use settings from specified login class]:class'
       '-f[if the invoked shell is csh, prevent it from reading .cshrc]'
       '(-m)-l[use a login shell]'
       "(-l)-m[don't reset environment]"
     )
   ;|
+  *bsd*|dragonfly*)
+    args+=(
+      '-c+[use settings from specified login class]:class'
+    )
+  ;|
   freebsd*) args+=( '-s[set the MAC label]' ) ;;
   openbsd*)
     args+=(
-      '(-K)-a[specify authentication type]:authentication type'
+      # See login.conf(5)
+      '(-K)-a+[specify authentication type]:authentication type:(
+        activ chpass crypto lchpass passwd radius reject skey snk token yubikey
+      )'
       '(-a)-K[shorthand for -a passwd]'
-      '-s[run the specified shell]:shell:->shells'
+      '-s+[run the specified shell]:shell:->shells'
       '-L[loop until login succeeds]'
     )
   ;;
@@ -57,13 +65,26 @@
 
 _arguments $args ${(e)first} "*:shell arguments:= ->rest" && return
 
-usr=${line[norm]/--/root}
-if (( $#opt_args[(i)-(s|-shell)] )); then
+usr=${${(Q)line[norm]}/--/root}
+# OpenBSD supports appending a log-in method to the user name, as in usr:radius
+[[ $OSTYPE == openbsd* ]] && usr=${usr%:*}
+
+# Normal users generally don't appear in passwd on macOS; try the Directory
+# Service first
+if [[ $OSTYPE == darwin* ]] && (( $+commands[dscl] )); then
+  shell=${"$(
+    _call_program shells dscl . -read /Users/${(q)usr} UserShell
+  )"#UserShell: }
+fi
+
+if [[ -n $shell ]]; then
+  : # Found above
+elif (( ${#${(@M)args:#*-s[+\[]*:*}} && $#opt_args[(i)-(s|-shell)] )); then
   shell=${(v)opt_args[(i)-(s|-shell)]}
 elif (( ${+commands[getent]} )); then
-  shell="${$(_call_program shells getent passwd $usr)##*:}"
+  shell="${$(_call_program shells getent passwd ${(q)usr})##*:}"
 else
-  shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
+  shell="${${(M@)${(@f)$(</etc/passwd)}:#${usr}:*}##*:}"
 fi
 
 case $state in
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Completion/Unix/Command/_zip 
new/zsh-5.8/Completion/Unix/Command/_zip
--- old/zsh-5.7.1-test-3/Completion/Unix/Command/_zip   2017-12-04 
15:09:35.000000000 +0100
+++ new/zsh-5.8/Completion/Unix/Command/_zip    2020-02-14 17:15:11.000000000 
+0100
@@ -82,7 +82,7 @@
       '*:file:->files' && ret=0
   ;;
   unzip)
-    _arguments -C -s \
+    _arguments -C -s -S \
       '(-Z)-M[page output]' \
       - unzip \
       '(-f -u -l -t -z -d -p)-c[extract files to stdout including file names]' 
\
@@ -130,7 +130,7 @@
 [[ $state == zipinfo ]] && uzi="-Z[zipinfo mode]"
 
 if [[ $service == zipinfo ]] || [[ -n $uzi ]]; then
-    _arguments -C -s \
+    _arguments -C -s -S \
       $uzi \
       '(-2 -s -m -l -v -h -t -T -z)-1[filenames only]' \
       '(-1 -s -m -l -v -T)-2[just filenames but allow -h/-t/-z]' \
@@ -170,7 +170,7 @@
       fi 2>/dev/null
       if [[ $zipfile !=  $_zip_cache_name ]]; then
        _zip_cache_name="$zipfile"
-       _zip_cache_list=( ${(f)"$(zipinfo -1 $_zip_cache_name)"} )
+       _zip_cache_list=( ${(f)"$(zipinfo -1 -- $_zip_cache_name)"} )
       fi
      _wanted files expl 'file from archive' \
         _multi_parts / _zip_cache_list && return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Config/version.mk 
new/zsh-5.8/Config/version.mk
--- old/zsh-5.7.1-test-3/Config/version.mk      2020-02-06 20:56:06.000000000 
+0100
+++ new/zsh-5.8/Config/version.mk       2020-02-14 23:11:10.000000000 +0100
@@ -27,5 +27,5 @@
 # This must also serve as a shell script, so do not add spaces around the
 # `=' signs.
 
-VERSION=5.7.1-test-3
-VERSION_DATE='February 6, 2020'
+VERSION=5.8
+VERSION_DATE='February 14, 2020'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/version.yo 
new/zsh-5.8/Doc/version.yo
--- old/zsh-5.7.1-test-3/Doc/version.yo 2020-02-06 21:06:20.000000000 +0100
+++ new/zsh-5.8/Doc/version.yo  2020-02-14 23:13:00.000000000 +0100
@@ -1,6 +1,6 @@
 IFDEF(INCWSLEVEL)(INCWSLEVEL())(STARTDEF())
-def(version)(0)(5.7.1-test-3)
-def(date)(0)(February 6, 2020)
+def(version)(0)(5.8)
+def(date)(0)(February 14, 2020)
 def(zshenv)(0)(/etc/zshenv)
 def(zprofile)(0)(/etc/zprofile)
 def(zshrc)(0)(/etc/zshrc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zsh.1 new/zsh-5.8/Doc/zsh.1
--- old/zsh-5.7.1-test-3/Doc/zsh.1      2020-02-06 21:06:20.000000000 +0100
+++ new/zsh-5.8/Doc/zsh.1       2020-02-14 23:13:01.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSH" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSH" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zsh \- the Z shell
 .\" Yodl file: Zsh/intro.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zsh.texi 
new/zsh-5.8/Doc/zsh.texi
--- old/zsh-5.7.1-test-3/Doc/zsh.texi   2020-02-06 21:06:27.000000000 +0100
+++ new/zsh-5.8/Doc/zsh.texi    2020-02-14 23:13:08.000000000 +0100
@@ -27,8 +27,8 @@
 @end iftex
 @titlepage
 @title The Z Shell Manual
-@subtitle Version 5.7.1-test-3
-@subtitle Updated February 6, 2020
+@subtitle Version 5.8
+@subtitle Updated February 14, 2020
 @author Original documentation by Paul Falstad
 @page
 This is a texinfo version of the documentation for the Z Shell, originally by 
@@ -63,7 +63,7 @@
 
 @noindent
 @cindex version
-Version 5.7.1-test-3, last updated February 6, 2020.
+Version 5.8, last updated February 14, 2020.
 @end ifinfo
 
 @menu
@@ -34876,7 +34876,7 @@
 @noindent
 @example
 mkdir ~/zsh_help
-perl ~/zsh-5.7.1-test-3/Util/helpfiles ~/zsh_help
+perl ~/zsh-5.8/Util/helpfiles ~/zsh_help
 @end example
 
 @noindent
@@ -35037,7 +35037,7 @@
 
 @noindent
 @example
-zsh -f ~/zsh-5.7.1-test-3/Functions/Misc/zkbd
+zsh -f ~/zsh-5.8/Functions/Misc/zkbd
 @end example
 
 @noindent
@@ -35102,7 +35102,7 @@
 
 @noindent
 @example
-. ~/zsh-5.7.1-test-3/Util/reporter > zsh.report
+. ~/zsh-5.8/Util/reporter > zsh.report
 @end example
 
 @noindent
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshall.1 
new/zsh-5.8/Doc/zshall.1
--- old/zsh-5.7.1-test-3/Doc/zshall.1   2020-02-06 21:06:24.000000000 +0100
+++ new/zsh-5.8/Doc/zshall.1    2020-02-14 23:13:05.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHALL" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHALL" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshall \- the Z shell meta\-man page
 .\" Yodl file: Zsh/intro.yo
@@ -476,7 +476,7 @@
 .so man1/zshtcpsys.1
 .so man1/zshzftpsys.1
 .so man1/zshcontrib.1
-.TH "ZSHALL" "1" "February 6, 2020" "zsh 5\&.7\&.1\-test\-3"
+.TH "ZSHALL" "1" "February 14, 2020" "zsh 5\&.8"
 .\" Yodl file: Zsh/filelist.yo
 .SH "FILES"
 .PD 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshbuiltins.1 
new/zsh-5.8/Doc/zshbuiltins.1
--- old/zsh-5.7.1-test-3/Doc/zshbuiltins.1      2020-02-06 21:06:20.000000000 
+0100
+++ new/zsh-5.8/Doc/zshbuiltins.1       2020-02-14 23:13:01.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHBUILTINS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHBUILTINS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshbuiltins \- zsh built\-in commands
 .\" Yodl file: Zsh/builtins.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshcalsys.1 
new/zsh-5.8/Doc/zshcalsys.1
--- old/zsh-5.7.1-test-3/Doc/zshcalsys.1        2020-02-06 21:06:21.000000000 
+0100
+++ new/zsh-5.8/Doc/zshcalsys.1 2020-02-14 23:13:01.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHCALSYS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHCALSYS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshcalsys \- zsh calendar system
 .\" Yodl file: Zsh/calsys.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshcompctl.1 
new/zsh-5.8/Doc/zshcompctl.1
--- old/zsh-5.7.1-test-3/Doc/zshcompctl.1       2020-02-06 21:06:21.000000000 
+0100
+++ new/zsh-5.8/Doc/zshcompctl.1        2020-02-14 23:13:01.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHCOMPCTL" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHCOMPCTL" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshcompctl \- zsh programmable completion
 .\" Yodl file: Zsh/compctl.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshcompsys.1 
new/zsh-5.8/Doc/zshcompsys.1
--- old/zsh-5.7.1-test-3/Doc/zshcompsys.1       2020-02-06 21:06:21.000000000 
+0100
+++ new/zsh-5.8/Doc/zshcompsys.1        2020-02-14 23:13:02.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHCOMPSYS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHCOMPSYS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshcompsys \- zsh completion system
 .\" Yodl file: Zsh/compsys.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshcompwid.1 
new/zsh-5.8/Doc/zshcompwid.1
--- old/zsh-5.7.1-test-3/Doc/zshcompwid.1       2020-02-06 21:06:21.000000000 
+0100
+++ new/zsh-5.8/Doc/zshcompwid.1        2020-02-14 23:13:01.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHCOMPWID" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHCOMPWID" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshcompwid \- zsh completion widgets
 .\" Yodl file: Zsh/compwid.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshcontrib.1 
new/zsh-5.8/Doc/zshcontrib.1
--- old/zsh-5.7.1-test-3/Doc/zshcontrib.1       2020-02-06 21:06:22.000000000 
+0100
+++ new/zsh-5.8/Doc/zshcontrib.1        2020-02-14 23:13:02.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHCONTRIB" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHCONTRIB" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshcontrib \- user contributions to zsh
 .\" Yodl file: Zsh/contrib.yo
@@ -41,7 +41,7 @@
 .RS
 .nf
 \fBmkdir ~/zsh_help
-perl ~/zsh\-5\&.7\&.1\-test\-3/Util/helpfiles ~/zsh_help\fP
+perl ~/zsh\-5\&.8/Util/helpfiles ~/zsh_help\fP
 .fi
 .RE
 .PP
@@ -181,7 +181,7 @@
 .PP
 .RS
 .nf
-\fBzsh \-f ~/zsh\-5\&.7\&.1\-test\-3/Functions/Misc/zkbd\fP
+\fBzsh \-f ~/zsh\-5\&.8/Functions/Misc/zkbd\fP
 .fi
 .RE
 .PP
@@ -237,7 +237,7 @@
 .PP
 .RS
 .nf
-\fB\&. ~/zsh\-5\&.7\&.1\-test\-3/Util/reporter > zsh\&.report\fP
+\fB\&. ~/zsh\-5\&.8/Util/reporter > zsh\&.report\fP
 .fi
 .RE
 .PP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshexpn.1 
new/zsh-5.8/Doc/zshexpn.1
--- old/zsh-5.7.1-test-3/Doc/zshexpn.1  2020-02-06 21:06:22.000000000 +0100
+++ new/zsh-5.8/Doc/zshexpn.1   2020-02-14 23:13:03.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHEXPN" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHEXPN" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshexpn \- zsh expansion and substitution
 .\" Yodl file: Zsh/expn.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshmisc.1 
new/zsh-5.8/Doc/zshmisc.1
--- old/zsh-5.7.1-test-3/Doc/zshmisc.1  2020-02-06 21:06:22.000000000 +0100
+++ new/zsh-5.8/Doc/zshmisc.1   2020-02-14 23:13:03.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHMISC" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHMISC" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshmisc \- everything and then some
 .\" Yodl file: Zsh/grammar.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshmodules.1 
new/zsh-5.8/Doc/zshmodules.1
--- old/zsh-5.7.1-test-3/Doc/zshmodules.1       2020-02-06 21:06:23.000000000 
+0100
+++ new/zsh-5.8/Doc/zshmodules.1        2020-02-14 23:13:03.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHMODULES" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHMODULES" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshmodules \- zsh loadable modules
 .\" Yodl file: Zsh/modules.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshoptions.1 
new/zsh-5.8/Doc/zshoptions.1
--- old/zsh-5.7.1-test-3/Doc/zshoptions.1       2020-02-06 21:06:23.000000000 
+0100
+++ new/zsh-5.8/Doc/zshoptions.1        2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHOPTIONS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHOPTIONS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshoptions \- zsh options
 .\" Yodl file: Zsh/options.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshparam.1 
new/zsh-5.8/Doc/zshparam.1
--- old/zsh-5.7.1-test-3/Doc/zshparam.1 2020-02-06 21:06:23.000000000 +0100
+++ new/zsh-5.8/Doc/zshparam.1  2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHPARAM" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHPARAM" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshparam \- zsh parameters
 .\" Yodl file: Zsh/params.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshroadmap.1 
new/zsh-5.8/Doc/zshroadmap.1
--- old/zsh-5.7.1-test-3/Doc/zshroadmap.1       2020-02-06 21:06:23.000000000 
+0100
+++ new/zsh-5.8/Doc/zshroadmap.1        2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHROADMAP" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHROADMAP" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshroadmap \- informal introduction to the zsh manual
 .\" Yodl file: Zsh/roadmap.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshtcpsys.1 
new/zsh-5.8/Doc/zshtcpsys.1
--- old/zsh-5.7.1-test-3/Doc/zshtcpsys.1        2020-02-06 21:06:23.000000000 
+0100
+++ new/zsh-5.8/Doc/zshtcpsys.1 2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHTCPSYS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHTCPSYS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshtcpsys \- zsh tcp system
 .\" Yodl file: Zsh/tcpsys.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshzftpsys.1 
new/zsh-5.8/Doc/zshzftpsys.1
--- old/zsh-5.7.1-test-3/Doc/zshzftpsys.1       2020-02-06 21:06:24.000000000 
+0100
+++ new/zsh-5.8/Doc/zshzftpsys.1        2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHZFTPSYS" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHZFTPSYS" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshzftpsys \- zftp function front\-end
 .\" Yodl file: Zsh/zftpsys.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Doc/zshzle.1 
new/zsh-5.8/Doc/zshzle.1
--- old/zsh-5.7.1-test-3/Doc/zshzle.1   2020-02-06 21:06:24.000000000 +0100
+++ new/zsh-5.8/Doc/zshzle.1    2020-02-14 23:13:04.000000000 +0100
@@ -1,4 +1,4 @@
-.TH "ZSHZLE" "1" "February 6, 2020" "zsh 5\&.7\&.1-test-3"
+.TH "ZSHZLE" "1" "February 14, 2020" "zsh 5\&.8"
 .SH "NAME"
 zshzle \- zsh command line editor
 .\" Yodl file: Zsh/zle.yo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/NEWS new/zsh-5.8/NEWS
--- old/zsh-5.7.1-test-3/NEWS   2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/NEWS    2020-02-14 23:06:58.000000000 +0100
@@ -4,8 +4,22 @@
 
 Note also the list of incompatibilities in the README file.
 
-Changes since 5.7.1
--------------------
+Changes since 5.7.1-test-3
+--------------------------
+
+CVE-2019-20044: When unsetting the PRIVILEGED option, the shell sets its
+effective user and group IDs to match their respective real IDs. On some
+platforms (including Linux and macOS, but not FreeBSD), when the RUID and
+EUID were both non-zero, it was possible to regain the shell's former
+privileges by e.g. assigning to the EUID or EGID parameter. In the course
+of investigating this issue, it was also found that the setopt built-in
+did not correctly report errors when unsetting the option, which
+prevented users from handling them as the documentation recommended.
+setopt now returns non-zero if it is unable to safely drop privileges.
+[ Reported by Sam Foxman <[email protected]>. ]
+
+Changes from 5.7.1 to 5.7.1-test-3
+----------------------------------
 
 The zsh/zutil module's zparseopts builtin learnt an -F option to abort
 parsing when an unrecognised option-like parameter is encountered.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/README new/zsh-5.8/README
--- old/zsh-5.7.1-test-3/README 2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/README  2020-02-14 23:06:58.000000000 +0100
@@ -5,8 +5,9 @@
 Version
 -------
 
-This is version 5.8 of the shell.  This is a stable release.  There are
-a few visible improvements since 5.7 as well as many bugfixes.
+This is version 5.8 of the shell.  This is a security and feature release.
+There are a few visible improvements since 5.7, as well as many bugfixes.
+All zsh installations are encouraged to upgrade as soon as possible.
 
 Note in particular the changes highlighted under "Incompatibilities since
 5.7.1" below.  See NEWS for more information.
@@ -56,6 +57,12 @@
 The cd and chdir builtins no longer interpret operands like -1 and +2 as
 stack entries when POSIX_CD is enabled.
 
+Dropping privileges with `unsetopt privileged` may fail (with an error
+message) on some older and uncommon platforms due to library dependency
+changes made in the course of fixing CVE-2019-20044.  Please report this
+to the zsh-workers mailing list if your system is affected.  See NEWS for
+more.
+
 Incompatibilities between 5.6.2 and 5.7.1
 -----------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Src/openssh_bsd_setres_id.c 
new/zsh-5.8/Src/openssh_bsd_setres_id.c
--- old/zsh-5.7.1-test-3/Src/openssh_bsd_setres_id.c    1970-01-01 
01:00:00.000000000 +0100
+++ new/zsh-5.8/Src/openssh_bsd_setres_id.c     2020-02-14 23:06:57.000000000 
+0100
@@ -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 <sys/types.h>
+
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+
+#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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Src/options.c 
new/zsh-5.8/Src/options.c
--- old/zsh-5.7.1-test-3/Src/options.c  2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/Src/options.c   2020-02-14 23:06:57.000000000 +0100
@@ -577,6 +577,7 @@
 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) {
@@ -604,18 +605,24 @@
                    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))
+                   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);
-               else if(dosetopt(optno, action, 0, opts))
+                   retval |= 1;
+               } else if (dosetopt(optno, action, 0, opts)) {
                    zwarnnam(nam, "can't change option: -%c", **args);
+                   retval |= 1;
+               }
            }
        }
        args++;
@@ -625,10 +632,13 @@
     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))
+               retval |= 1;
+           } else if (dosetopt(optno, !isun, 0, opts)) {
                zwarnnam(nam, "can't change option: %s", args[-1]);
+               retval |= 1;
+           }
        }
     } else {
        /* Globbing option (-m) set. */
@@ -651,7 +661,8 @@
            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,
@@ -660,7 +671,7 @@
        }
     }
     inittyptab();
-    return 0;
+    return retval;
 }
 
 /* Identify an option name */
@@ -769,37 +780,99 @@
            return -1;
     } else if(optno == PRIVILEGED && !value) {
        /* unsetting PRIVILEGED causes the shell to make itself unprivileged */
-#ifdef HAVE_SETUID
-       int ignore_err;
-       errno = 0;
+
+/* 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;
+       const int orig_euid = geteuid();
+       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.
-        *
-        * Some OSes (possibly no longer around) have been known to
-        * fail silently the first time, so we attempt the change twice.
-        * If it fails we are guaranteed to pick this up the second
-        * time, so ignore the first time.
-        *
-        * Some versions of gcc make it hard to ignore the results the
-        * first time, hence the following.  (These are probably not
-        * systems that require the doubled calls.)
         */
-       ignore_err = setgid(getgid());
-       (void)ignore_err;
-       ignore_err = setuid(getuid());
-       (void)ignore_err;
-       if (setgid(getgid())) {
-            zwarn("failed to change group ID: %e", errno);
-            return -1;
-        } else if (setuid(getuid())) {
-            zwarn("failed to change user ID: %e", errno);
-            return -1;
+       if (setresgid(getgid(), getgid(), getgid())) {
+           zwarnnam("unsetopt",
+               "PRIVILEGED: can't drop privileges; failed to change group ID: 
%e",
+               errno);
+           return -1;
        }
-#else
-        zwarn("setuid not available");
-        return -1;
-#endif /* not HAVE_SETUID */
+
+# ifdef HAVE_INITGROUPS
+       /* 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. */
+# 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;
+       }
+
+       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;
+       }
+
+       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;
+       }
+
+       if (failed) {
+           /* A warning message has been printed. */
+           return -1;
+       }
+#endif /* HAVE_SETRESGID && HAVE_SETRESUID */
+
 #ifdef JOB_CONTROL
     } else if (!force && optno == MONITOR && value) {
        if (new_opts[optno] == value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Src/patchlevel.h.release 
new/zsh-5.8/Src/patchlevel.h.release
--- old/zsh-5.7.1-test-3/Src/patchlevel.h.release       2020-02-06 
21:07:33.000000000 +0100
+++ new/zsh-5.8/Src/patchlevel.h.release        2020-02-14 23:16:14.000000000 
+0100
@@ -1 +1 @@
-#define ZSH_PATCHLEVEL "zsh-5.7.1-test-3-0-g643de93"
+#define ZSH_PATCHLEVEL "zsh-5.8-0-g77d203f"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Src/zsh.mdd new/zsh-5.8/Src/zsh.mdd
--- old/zsh-5.7.1-test-3/Src/zsh.mdd    2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/Src/zsh.mdd     2020-02-14 23:06:57.000000000 +0100
@@ -13,7 +13,8 @@
 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Src/zsh_system.h 
new/zsh-5.8/Src/zsh_system.h
--- old/zsh-5.7.1-test-3/Src/zsh_system.h       2020-02-03 06:52:13.000000000 
+0100
+++ new/zsh-5.8/Src/zsh_system.h        2020-02-14 23:06:57.000000000 +0100
@@ -468,30 +468,90 @@
 # 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
+
+/* 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
 
-/* can we set the effective user/group id of a process */
+/* 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Test/E01options.ztst 
new/zsh-5.8/Test/E01options.ztst
--- old/zsh-5.7.1-test-3/Test/E01options.ztst   2020-02-03 06:52:13.000000000 
+0100
+++ new/zsh-5.8/Test/E01options.ztst    2020-02-14 23:06:58.000000000 +0100
@@ -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
@@ -1391,3 +1399,18 @@
 ?(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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Test/P01privileged.ztst 
new/zsh-5.8/Test/P01privileged.ztst
--- old/zsh-5.7.1-test-3/Test/P01privileged.ztst        1970-01-01 
01:00:00.000000000 +0100
+++ new/zsh-5.8/Test/P01privileged.ztst 2020-02-14 23:06:58.000000000 +0100
@@ -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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Test/README new/zsh-5.8/Test/README
--- old/zsh-5.7.1-test-3/Test/README    2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/Test/README     2020-02-14 23:06:58.000000000 +0100
@@ -6,6 +6,7 @@
  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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/Test/V01zmodload.ztst 
new/zsh-5.8/Test/V01zmodload.ztst
--- old/zsh-5.7.1-test-3/Test/V01zmodload.ztst  2018-11-13 09:04:43.000000000 
+0100
+++ new/zsh-5.8/Test/V01zmodload.ztst   2020-02-14 23:07:11.000000000 +0100
@@ -348,6 +348,22 @@
 ?(eval):6: unknown function: systell
 ?(eval):9: file descriptor out of range
 
+ $ZTST_testdir/../Src/zsh -fc "
+  MODULE_PATH=${(q)MODULE_PATH}
+  #
+  zmodload zsh/zutil
+  zmodload -Fal zsh/zutil | grep parse
+  zmodload -u zsh/zutil
+  #
+  zmodload -Fa zsh/zutil -b:zregexparse
+  zmodload zsh/zutil
+  zmodload -Fal zsh/zutil | grep parse >&2
+ "
+0:zmodload -Fa can disable features from being loaded
+>b:zparseopts
+>b:zregexparse
+?b:zparseopts
+
 %clean
 
  eval "$deps"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/config.h.in new/zsh-5.8/config.h.in
--- old/zsh-5.7.1-test-3/config.h.in    2020-01-12 04:43:21.000000000 +0100
+++ new/zsh-5.8/config.h.in     2020-02-14 18:38:46.000000000 +0100
@@ -613,12 +613,18 @@
 /* Define to 1 if you have the `setcchar' function. */
 #undef HAVE_SETCCHAR
 
+/* Define to 1 if you have the `setegid' function. */
+#undef HAVE_SETEGID
+
 /* Define to 1 if you have the `setenv' function. */
 #undef HAVE_SETENV
 
 /* Define to 1 if you have the `seteuid' function. */
 #undef HAVE_SETEUID
 
+/* Define to 1 if you have the `setgid' function. */
+#undef HAVE_SETGID
+
 /* Define to 1 if you have the `setlocale' function. */
 #undef HAVE_SETLOCALE
 
@@ -631,6 +637,12 @@
 /* Define to 1 if the system supports `setproctitle' to change process name */
 #undef HAVE_SETPROCTITLE
 
+/* Define to 1 if you have the `setregid' function. */
+#undef HAVE_SETREGID
+
+/* Define to 1 if you have the `setresgid' function. */
+#undef HAVE_SETRESGID
+
 /* Define to 1 if you have the `setresuid' function. */
 #undef HAVE_SETRESUID
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/configure new/zsh-5.8/configure
--- old/zsh-5.7.1-test-3/configure      2020-02-06 20:53:57.000000000 +0100
+++ new/zsh-5.8/configure       2020-02-14 23:11:48.000000000 +0100
@@ -8661,6 +8661,7 @@
               getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
               initgroups nis_list \
               setuid seteuid setreuid setresuid setsid \
+              setgid setegid setregid setresgid \
               memcpy memmove strstr strerror strtoul \
               getrlimit getrusage \
               setlocale \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/zsh-5.7.1-test-3/configure.ac 
new/zsh-5.8/configure.ac
--- old/zsh-5.7.1-test-3/configure.ac   2020-02-03 06:52:13.000000000 +0100
+++ new/zsh-5.8/configure.ac    2020-02-14 23:06:57.000000000 +0100
@@ -1311,6 +1311,7 @@
               getlogin getpwent getpwnam getpwuid getgrgid getgrnam \
               initgroups nis_list \
               setuid seteuid setreuid setresuid setsid \
+              setgid setegid setregid setresgid \
               memcpy memmove strstr strerror strtoul \
               getrlimit getrusage \
               setlocale \



Reply via email to