Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bug#862907: dash: Incorrectly slurps script from stdin (POSIX compliance issue)

33 views
Skip to first unread message

Guillem Jover

unread,
May 18, 2017, 10:20:03 AM5/18/17
to
Package: dash
Version: 0.5.8-2.4
Severity: normal
Tags: upstream
X-Debbugs-CC: Michael Prokop <mpr...@sipwise.com>

Hi!

While tracking an issue with some scripts (described at [I]) we noticed
that dash is not POSIX compliant when parsing the script to invoke
from stdin. In contradiction with POSIX, it does block reads instead
of character-per-character reads to only get the current command,
quoting from POSIX [P]:

,---
| STDIN
|
| […]
|
| When the shell is using standard input and it invokes a command that
| also uses standard input, the shell shall ensure that the standard
| input file pointer points directly after the command it has read
| when the command begins execution. It shall not read ahead in such a
| manner that any characters intended to be read by the invoked
| command are consumed by the shell (whether interpreted by the shell
| or not) or that characters that are not read by the invoked command
| are not seen by the shell. When the command expecting to read
| standard input is started asynchronously by an interactive shell, it
| is unspecified whether characters are read by the command or
| interpreted by the shell.
`---

[I] <https://michael-prokop.at/blog/2017/05/18/debugging-a-mystery-ssh-causing-strange-exit-codes/>
[P] <http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sh.html>

The following test demonstrates the problem:

,--- sh-stdin.sh ---
#!/bin/sh

: ${TEST_SH:=dash}

$TEST_SH <<"EOF"
echo "Inner: pre"
while read line; do echo "Eat: $line"; done
echo "Inner: post"
exit 3
EOF

echo "Outer: exit code = $?"
`---

,--- test session ---
$ TEST_SH=bash ./sh-stdin
Inner: pre
Eat: echo "Inner: post"
Eat: exit 3
Outer: exit code = 0
$ TEST_SH=dash ./stdin.sh
Inner: pre
Inner: post
Outer: exit code = 3
`---

All other shells that we tested are POSIX compliant, this includes:

bash, ksh, mksh, posh and zsh

Thanks,
Guillem

наб

unread,
Dec 13, 2022, 5:30:05 PM12/13/22
to
Control: forwarded -1 https://lore.kernel.org/dash/20221213221732....@tarta.nabijaczleweli.xyz/t/

Looks like a trivial one-line fix to, quite literally,
read with count=1 if reading from the standard input stream;
patch posted to dash@, archived at forwarded-to.

наб
signature.asc

наб

unread,
Jan 8, 2023, 9:50:06 AM1/8/23
to
Control: tags -1 + fixed-upstream

Turns out it was /not/ a one-line fix, since it exposed a lot of other
latent bugs; either way, fixed upstream in this series:
https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=07cad228ae4d1567aeb6d13d2af83d0a28d13b67
https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=91a375576d37bb4db1eca48e6bf5bac0db6cc3fa
https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=5f094d08c5bcee876191404a4f3dd2d075571215
https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=44ae22beedf8a3d68bbfa1d065ad677182372de2
(I think that's the smallest viable part of the fix, anyway).

All test cases work on trunk, including your original reproducer:
$ src/dash <<EOF
id
cat
good!
EOF
uid=1000(nabijaczleweli) gid=100(users) groups=100(users),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev),109(ssh),113(debian-transmission),116(kvm),120(minidlna),1000(nabijaczleweli),1002(smb-share),1006(smb-spool)
good!
$ src/dash <<"EOF"
id
read Q
good!
echo Q$Q
EOF
uid=1000(nabijaczleweli) gid=100(users) groups=100(users),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),108(netdev),109(ssh),113(debian-transmission),116(kvm),120(minidlna),1000(nabijaczleweli),1002(smb-share),1006(smb-spool)
Qgood!
$ echo "|$(printf %10000s)echo bug" | src/dash -i
$ src/dash: 1: Syntax error: "|" unexpected
$
src/dash: 1: Cannot set tty process group (No such process)
$ TEST_SH=src/dash ./sh-stdin.sh
Inner: pre
Eat: echo "Inner: post"
Eat: exit 3
Outer: exit code = 0

наб
signature.asc
0 new messages