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

Package:
dash
Source:
dash
Description:
POSIX-compliant shell
Submitter:
Guillem Jover
Date:
2024-06-29 06:06:02 UTC
Severity:
normal
Tags:
#862907#5
Date:
2017-05-18 14:15:09 UTC
From:
To:
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

#862907#10
Date:
2022-12-13 22:22:38 UTC
From:
To:
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.

наб

#862907#19
Date:
2023-01-08 14:39:05 UTC
From:
To:
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

наб

#862907#26
Date:
2024-06-29 06:02:49 UTC
From:
To:
The issue has been raised another time on the debian-user mailing list,
so I have decided to look closer at it. Even more commits are required, see

Herbert Xu. [v3 PATCH 0/3] Improve performance when reading stdin.
Sun, 02 Jun 2024 09:31:30 +0800
https://lore.kernel.org/dash/cover.1717291846.git.herbert@gondor.apana.org.au/t/#u

Accordingly to earlier commit messages, impact on performance was
considered unimportant.

I have not tried to find commits adding unit tests covering the issue.

Initially I had a hope that it may be safe to add patches to Debian
package before next dash release, but now I am less sure.