ksh: failing eval stops execution even when in OR-list

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

ksh: failing eval stops execution even when in OR-list

Leah Neukirchen
>Synopsis: ksh: failing eval stops execution even when in OR-list
>Category: user
>Environment:
        System      : OpenBSD 6.6
        Details     : OpenBSD 6.6 (GENERIC.MP) #3: Thu Nov 21 03:20:01 MST 2019
                          [hidden email]:/usr/src/sys/arch/amd64/compile/GENERIC.MP

        Architecture: OpenBSD.amd64
        Machine     : amd64
>Description:
When under "set -e", using "eval" in an OR-list, a failure during evaluation
of the eval string will stop the shell, and not trigger the OR-list:

set -e
eval false || true
echo pass

Output of this script on OpenBSD:

$ sh sete.sh ; echo $?
1

Output with various other shells:

% ksh93 sete.sh
pass
% dash sete.sh
pass
% posh sete.sh
pass
% yash sete.sh
pass
% mksh sete.sh
pass
% bash sete.sh
pass
% zsh sete.sh
pass
% busybox sh sete.sh
pass

I think this is in violation of the POSIX 2008 specification:
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
> The -e setting shall be ignored when executing the compound list
> following the while, until, if, or elif reserved word, a pipeline
> beginning with the ! reserved word, or any command of an AND-OR list
> other than the last.

>How-To-Repeat:
Running this script as a reproducer:

set -e
eval false || true
echo pass

>Fix:
As a workaround: eval "false || true" || true

Thanks,
--
Leah Neukirchen  <[hidden email]>  https://leahneukirchen.org/

Reply | Threaded
Open this post in threaded view
|

Re: ksh: failing eval stops execution even when in OR-list

Leah Neukirchen
Leah Neukirchen <[hidden email]> writes:

>>Synopsis: ksh: failing eval stops execution even when in OR-list

I noticed this issue else appears only in pdksh, but not in mksh.
Bisecting mksh I found this fixed between R21 and R22,
in this commit:
https://github.com/MirBSD/mksh/commit/ba859c9ab1d7bae5a70c0d094f5a39669e8f81ef

This Debian bug report from 2004 shows that it also occured in
other shells that fixed it since then:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=269067

Here's a patch that fixes it, but it's more an idea of what someone
experienced with the code base could look for:

--- a/c_sh.c
+++ b/c_sh.c
@@ -424,6 +424,8 @@ int
 c_eval(char **wp)
 {
        struct source *s;
+       struct source *saves = source;
+       int savef;
        int rv;
 
        if (ksh_getopt(wp, &builtin_opt, null) == '?')
@@ -458,7 +460,11 @@ c_eval(char **wp)
                exstat = subst_exstat;
        }
 
+       savef = Flag(FERREXIT);
+       Flag(FERREXIT) = 0;
        rv = shell(s, false);
+       Flag(FERREXIT) = savef;
+       source = saves;
        afree(s, ATEMP);
        return (rv);
 }


Cheers,
--
Leah Neukirchen  <[hidden email]>  https://leahneukirchen.org/

Reply | Threaded
Open this post in threaded view
|

Re: ksh: failing eval stops execution even when in OR-list

Sebastian Benoit-3
Hi Leah,

thanks for your report and researching this!

Anyone else happy with this?
I'd like to commit it ;)

/Benno

Leah Neukirchen([hidden email]) on 2020.05.20 21:18:09 +0200:

> Leah Neukirchen <[hidden email]> writes:
>
> >>Synopsis: ksh: failing eval stops execution even when in OR-list
>
> I noticed this issue else appears only in pdksh, but not in mksh.
> Bisecting mksh I found this fixed between R21 and R22,
> in this commit:
> https://github.com/MirBSD/mksh/commit/ba859c9ab1d7bae5a70c0d094f5a39669e8f81ef
>
> This Debian bug report from 2004 shows that it also occured in
> other shells that fixed it since then:
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=269067
>
> Here's a patch that fixes it, but it's more an idea of what someone
> experienced with the code base could look for:
>
> --- a/c_sh.c
> +++ b/c_sh.c
> @@ -424,6 +424,8 @@ int
>  c_eval(char **wp)
>  {
>         struct source *s;
> +       struct source *saves = source;
> +       int savef;
>         int rv;
>  
>         if (ksh_getopt(wp, &builtin_opt, null) == '?')
> @@ -458,7 +460,11 @@ c_eval(char **wp)
>                 exstat = subst_exstat;
>         }
>  
> +       savef = Flag(FERREXIT);
> +       Flag(FERREXIT) = 0;
>         rv = shell(s, false);
> +       Flag(FERREXIT) = savef;
> +       source = saves;
>         afree(s, ATEMP);
>         return (rv);
>  }
>
>
> Cheers,
> --
> Leah Neukirchen  <[hidden email]>  https://leahneukirchen.org/
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh: failing eval stops execution even when in OR-list

Todd C. Miller-3
On Fri, 22 May 2020 00:06:28 +0200, Sebastian Benoit wrote:

> Hi Leah,
>
> thanks for your report and researching this!
>
> Anyone else happy with this?
> I'd like to commit it ;)

Yes, OK millert@

 - todd

Reply | Threaded
Open this post in threaded view
|

Re: ksh: failing eval stops execution even when in OR-list

Sebastian Benoit-3
In reply to this post by Leah Neukirchen
Comitted, Thanks!

Leah Neukirchen([hidden email]) on 2020.05.20 21:18:09 +0200:

> Leah Neukirchen <[hidden email]> writes:
>
> >>Synopsis: ksh: failing eval stops execution even when in OR-list
>
> I noticed this issue else appears only in pdksh, but not in mksh.
> Bisecting mksh I found this fixed between R21 and R22,
> in this commit:
> https://github.com/MirBSD/mksh/commit/ba859c9ab1d7bae5a70c0d094f5a39669e8f81ef
>
> This Debian bug report from 2004 shows that it also occured in
> other shells that fixed it since then:
> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=269067
>
> Here's a patch that fixes it, but it's more an idea of what someone
> experienced with the code base could look for:
>
> --- a/c_sh.c
> +++ b/c_sh.c
> @@ -424,6 +424,8 @@ int
>  c_eval(char **wp)
>  {
>         struct source *s;
> +       struct source *saves = source;
> +       int savef;
>         int rv;
>  
>         if (ksh_getopt(wp, &builtin_opt, null) == '?')
> @@ -458,7 +460,11 @@ c_eval(char **wp)
>                 exstat = subst_exstat;
>         }
>  
> +       savef = Flag(FERREXIT);
> +       Flag(FERREXIT) = 0;
>         rv = shell(s, false);
> +       Flag(FERREXIT) = savef;
> +       source = saves;
>         afree(s, ATEMP);
>         return (rv);
>  }
>
>
> Cheers,
> --
> Leah Neukirchen  <[hidden email]>  https://leahneukirchen.org/
>