All of lore.kernel.org
 help / color / mirror / Atom feed
* Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e
@ 2022-08-18 11:44 наб
  2022-08-18 14:22 ` Michael Greenberg
  2022-12-07  3:59 ` [PATCH] eval: Check eflag after redirection error Herbert Xu
  0 siblings, 2 replies; 4+ messages in thread
From: наб @ 2022-08-18 11:44 UTC (permalink / raw)
  To: dash

[-- Attachment #1: Type: text/plain, Size: 3796 bytes --]

Hi!

Thought I'd forward this upstream, considering I already tested on
current git, and it's pretty grave.

https://bugs.debian.org/1017531, trimmed down a bit, follows:

----- Forwarded message from наб <nabijaczleweli@nabijaczleweli.xyz> -----

Subject: Bug#1017531: dash: for/while/if suppress errors from redirections
 with -e, POSIX violation

Dear Maintainer,

On current git (057cd650a4edd5856213d431a974ff35c6594489) and 0.5.11.5
the following holds:
-- >8 --
$ ./src/dash -ec 'while :; do :; done < /ENOENT; echo uhoh'
./src/dash: 1: cannot open /ENOENT: No such file
uhoh
$ ./src/dash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
./src/dash: 1: cannot open /ENOENT: No such file
uhoh
$ ./src/dash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
./src/dash: 1: cannot open /ENOENT: No such file
uhoh
-- >8 --

The correct output, as demonstrated by bash, is:
-- >8 --
$ bash -ec 'while :; do :; done < /ENOENT; echo uhoh'
bash: line 1: /ENOENT: No such file or directory
$ bash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
bash: line 1: /ENOENT: No such file or directory
$ bash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
bash: line 1: /ENOENT: No such file or directory
-- >8 --

This is a POSIX violation, and quite a grave one at that:
set -e is oft[1] used to guard against precisely this type of error!

The same happens if set -e is executed.

All quotes POSIX.1, Issue 7, TC2:
sh, OPTIONS:
  > The -a, -b, -C, -e, -f, -m, -n, -o option, -u, -v, and -x options
  > are described as part of the set utility in Special Built-In
  > Utilities. 

set, DESCRIPTION, -e:
  > When this option is on, when any command fails (for any of the
  > reasons listed in Consequences of Shell Errors or by returning an
  > exit status greater than zero), the shell immediately shall exit, as
  > if by executing the exit special built-in utility with no arguments,
  > with the following exceptions:
  >
  > 1. The failure of any individual command in a multi-command pipeline
  >    shall not cause the shell to exit. Only the failure of the
  >    pipeline itself shall be considered.
  > 2. 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.
  > 3. If the exit status of a compound command other than a subshell
  >    command was the result of a failure while -e was being ignored,
  >    then -e shall not apply to this command.

XCU, 2.9.4: Shell Command Language, Shell Commands, Compound Commands:
The while Loop:
  > The format of the while loop is as follows:
  > 
  > while compound-list-1
  > do
  >   compound-list-2
  > done
(until is equivalent).
The if Conditional Construct: 
  > The format for the if construct is as follows:
  >
  > if compound-list
  > then
  >   compound-list
  > [elif compound-list
  > then
  >   compound-list] ...
  > [else
  >   compound-list]
  > fi

It follows, therefore, that
  * Exception 1. does not apply as there is no pipeline
  * Exception 2. does not apply, as the redirection does /not/ follow
    "while" or "if" directly and is /not/ part of the conditional
	compound-list
  * in the "for" case, there is no such provision, so this is likely not
    a confusion w.r.t. the conditional compound-lists
  * Exception 3. does not apply as -e was not being ignored while the
    compound commands were being executed (indeed, the compound commands
    do not run at all, as evidenced by the program terminating)

[1]: https://salsa.debian.org/glibc-team/glibc/-/merge_requests/6#note_329899
----- End forwarded message -----

Best,
наб

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e
  2022-08-18 11:44 Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e наб
@ 2022-08-18 14:22 ` Michael Greenberg
  2022-08-18 15:02   ` наб
  2022-12-07  3:59 ` [PATCH] eval: Check eflag after redirection error Herbert Xu
  1 sibling, 1 reply; 4+ messages in thread
From: Michael Greenberg @ 2022-08-18 14:22 UTC (permalink / raw)
  To: наб, dash

This looks like a serious bug... nice find!

I just checked my reference semantics shell (smoosh), and it fails this
test as well. Notably, smoosh passes the POSIX test suite---which means
that the POSIX folks are not properly testing for this behavior.

Also: what version of bash are you running? I suspect the fix to this in
bash is fairly recent.

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-apple-darwin17.7.0)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ bash -ec 'while :; do :; done < /ENOENT; echo uhoh'
bash: /ENOENT: No such file or directory
uhoh

$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.
$ /bin/bash -ec 'while :; do :; done < /ENOENT; echo uhoh'
/bin/bash: /ENOENT: No such file or directory
uhoh

Cheers,
Michael

On 2022-08-18 at 01:44:12 PM, наб wrote:

> Hi!
>
> Thought I'd forward this upstream, considering I already tested on
> current git, and it's pretty grave.
>
> https://bugs.debian.org/1017531, trimmed down a bit, follows:
>
> ----- Forwarded message from наб <nabijaczleweli@nabijaczleweli.xyz> -----
>
> Subject: Bug#1017531: dash: for/while/if suppress errors from redirections
>  with -e, POSIX violation
>
> Dear Maintainer,
>
> On current git (057cd650a4edd5856213d431a974ff35c6594489) and 0.5.11.5
> the following holds:
> -- >8 --
> $ ./src/dash -ec 'while :; do :; done < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> $ ./src/dash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> $ ./src/dash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> -- >8 --
>
> The correct output, as demonstrated by bash, is:
> -- >8 --
> $ bash -ec 'while :; do :; done < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> $ bash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> $ bash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> -- >8 --
>
> This is a POSIX violation, and quite a grave one at that:
> set -e is oft[1] used to guard against precisely this type of error!
>
> The same happens if set -e is executed.
>
> All quotes POSIX.1, Issue 7, TC2:
> sh, OPTIONS:
>   > The -a, -b, -C, -e, -f, -m, -n, -o option, -u, -v, and -x options
>   > are described as part of the set utility in Special Built-In
>   > Utilities. 
>
> set, DESCRIPTION, -e:
>   > When this option is on, when any command fails (for any of the
>   > reasons listed in Consequences of Shell Errors or by returning an
>   > exit status greater than zero), the shell immediately shall exit, as
>   > if by executing the exit special built-in utility with no arguments,
>   > with the following exceptions:
>   >
>   > 1. The failure of any individual command in a multi-command pipeline
>   >    shall not cause the shell to exit. Only the failure of the
>   >    pipeline itself shall be considered.
>   > 2. 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.
>   > 3. If the exit status of a compound command other than a subshell
>   >    command was the result of a failure while -e was being ignored,
>   >    then -e shall not apply to this command.
>
> XCU, 2.9.4: Shell Command Language, Shell Commands, Compound Commands:
> The while Loop:
>   > The format of the while loop is as follows:
>   > 
>   > while compound-list-1
>   > do
>   >   compound-list-2
>   > done
> (until is equivalent).
> The if Conditional Construct: 
>   > The format for the if construct is as follows:
>   >
>   > if compound-list
>   > then
>   >   compound-list
>   > [elif compound-list
>   > then
>   >   compound-list] ...
>   > [else
>   >   compound-list]
>   > fi
>
> It follows, therefore, that
>   * Exception 1. does not apply as there is no pipeline
>   * Exception 2. does not apply, as the redirection does /not/ follow
>     "while" or "if" directly and is /not/ part of the conditional
> 	compound-list
>   * in the "for" case, there is no such provision, so this is likely not
>     a confusion w.r.t. the conditional compound-lists
>   * Exception 3. does not apply as -e was not being ignored while the
>     compound commands were being executed (indeed, the compound commands
>     do not run at all, as evidenced by the program terminating)
>
> [1]: https://salsa.debian.org/glibc-team/glibc/-/merge_requests/6#note_329899
> ----- End forwarded message -----
>
> Best,
> наб

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e
  2022-08-18 14:22 ` Michael Greenberg
@ 2022-08-18 15:02   ` наб
  0 siblings, 0 replies; 4+ messages in thread
From: наб @ 2022-08-18 15:02 UTC (permalink / raw)
  To: Michael Greenberg; +Cc: dash

[-- Attachment #1: Type: text/plain, Size: 418 bytes --]

On Thu, Aug 18, 2022 at 10:22:25AM -0400, Michael Greenberg wrote:
> Also: what version of bash are you running? I suspect the fix to this in
> bash is fairly recent.
5.1-* off Debian; a simple default-config build+./bash -ec ... check
across the distribution tarballs shows that 4.4.18 and 5.0 are broken
in the same way as dash (and like your transcripts show),
but 5.1 produces the correct output.

наб

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] eval: Check eflag after redirection error
  2022-08-18 11:44 Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e наб
  2022-08-18 14:22 ` Michael Greenberg
@ 2022-12-07  3:59 ` Herbert Xu
  1 sibling, 0 replies; 4+ messages in thread
From: Herbert Xu @ 2022-12-07  3:59 UTC (permalink / raw)
  To: наб; +Cc: dash

наб <nabijaczleweli@nabijaczleweli.xyz> wrote:
> 
> Thought I'd forward this upstream, considering I already tested on
> current git, and it's pretty grave.
> 
> https://bugs.debian.org/1017531, trimmed down a bit, follows:
> 
> ----- Forwarded message from наб <nabijaczleweli@nabijaczleweli.xyz> -----
> 
> Subject: Bug#1017531: dash: for/while/if suppress errors from redirections
> with -e, POSIX violation
> 
> Dear Maintainer,
> 
> On current git (057cd650a4edd5856213d431a974ff35c6594489) and 0.5.11.5
> the following holds:
> -- >8 --
> $ ./src/dash -ec 'while :; do :; done < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> $ ./src/dash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> $ ./src/dash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
> ./src/dash: 1: cannot open /ENOENT: No such file
> uhoh
> -- >8 --
> 
> The correct output, as demonstrated by bash, is:
> -- >8 --
> $ bash -ec 'while :; do :; done < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> $ bash -ec 'for _ in :; do :; done < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> $ bash -ec 'if :; then :; fi < /ENOENT; echo uhoh'
> bash: line 1: /ENOENT: No such file or directory
> -- >8 --
> 
> This is a POSIX violation, and quite a grave one at that:
> set -e is oft[1] used to guard against precisely this type of error!
> 
> The same happens if set -e is executed.
> 
> All quotes POSIX.1, Issue 7, TC2:
> sh, OPTIONS:
>  > The -a, -b, -C, -e, -f, -m, -n, -o option, -u, -v, and -x options
>  > are described as part of the set utility in Special Built-In
>  > Utilities. 
> 
> set, DESCRIPTION, -e:
>  > When this option is on, when any command fails (for any of the
>  > reasons listed in Consequences of Shell Errors or by returning an
>  > exit status greater than zero), the shell immediately shall exit, as
>  > if by executing the exit special built-in utility with no arguments,
>  > with the following exceptions:
>  >
>  > 1. The failure of any individual command in a multi-command pipeline
>  >    shall not cause the shell to exit. Only the failure of the
>  >    pipeline itself shall be considered.
>  > 2. 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.
>  > 3. If the exit status of a compound command other than a subshell
>  >    command was the result of a failure while -e was being ignored,
>  >    then -e shall not apply to this command.
> 
> XCU, 2.9.4: Shell Command Language, Shell Commands, Compound Commands:
> The while Loop:
>  > The format of the while loop is as follows:
>  > 
>  > while compound-list-1
>  > do
>  >   compound-list-2
>  > done
> (until is equivalent).
> The if Conditional Construct: 
>  > The format for the if construct is as follows:
>  >
>  > if compound-list
>  > then
>  >   compound-list
>  > [elif compound-list
>  > then
>  >   compound-list] ...
>  > [else
>  >   compound-list]
>  > fi
> 
> It follows, therefore, that
>  * Exception 1. does not apply as there is no pipeline
>  * Exception 2. does not apply, as the redirection does /not/ follow
>    "while" or "if" directly and is /not/ part of the conditional
>        compound-list
>  * in the "for" case, there is no such provision, so this is likely not
>    a confusion w.r.t. the conditional compound-lists
>  * Exception 3. does not apply as -e was not being ignored while the
>    compound commands were being executed (indeed, the compound commands
>    do not run at all, as evidenced by the program terminating)
> 
> [1]: https://salsa.debian.org/glibc-team/glibc/-/merge_requests/6#note_329899
> ----- End forwarded message -----

Yes we should check the exit status after redirections.

Reported-by: наб <nabijaczleweli@nabijaczleweli.xyz>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/src/eval.c b/src/eval.c
index eda251e..7aa5cc2 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -246,15 +246,18 @@ evaltree(union node *n, int flags)
 			lineno -= funcline - 1;
 		expredir(n->nredir.redirect);
 		pushredir(n->nredir.redirect);
-		status = redirectsafe(n->nredir.redirect, REDIR_PUSH) ?:
-			 evaltree(n->nredir.n, flags & EV_TESTED);
+		status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
+		if (status)
+			checkexit = EV_TESTED;
+		else
+			status = evaltree(n->nredir.n, flags & EV_TESTED);
 		if (n->nredir.redirect)
 			popredir(0);
 		break;
 	case NCMD:
 		evalfn = evalcommand;
 checkexit:
-		checkexit = ~flags & EV_TESTED;
+		checkexit = EV_TESTED;
 		goto calleval;
 	case NFOR:
 		evalfn = evalfor;
@@ -316,7 +319,7 @@ calleval:
 out:
 	dotrap();
 
-	if (eflag && checkexit && status)
+	if (eflag && (~flags & checkexit) && status)
 		goto exexit;
 
 	if (flags & EV_EXIT) {
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-12-07  3:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-18 11:44 Fwd: Bug#1017531: dash: for/while/if suppress errors from redirections with -e наб
2022-08-18 14:22 ` Michael Greenberg
2022-08-18 15:02   ` наб
2022-12-07  3:59 ` [PATCH] eval: Check eflag after redirection error Herbert Xu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.