Re: [BUG] dash hangs on 'eval' syntax error in dot script

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 10/01/2019 14:21, Martijn Dekker wrote:
Op 10-01-19 om 11:37 schreef Martijn Dekker:
In a dot script sourced with 'command .' (which is useful to avoid
exiting if the script doesn't exist), triggering a syntax error in an
'eval' in a subshell causes dash to hang at the end of the main script.

In fact, 'eval' doesn't appear related. I can also trigger the bug by
triggering an error in another special builtin:

command . /dev/stdin <<EOF
( set -o foobar ) && echo WOOPS
EOF
echo end

I do not see a hang myself, but I definitely see wrong behaviour: the output I get is

  $ command . /dev/stdin <<EOF
  > ( set -o foobar ) && echo WOOPS
  > EOF
  src/dash: 1: set: Illegal option -o foobar
  $ echo end
  end
  $ <Ctrl-D>
  WOOPS
  $

This was introduced by

  commit 46d5a7fcea81b489819f753451c1ad2fe435f148
  Author: Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
  Date:   Tue Mar 27 00:39:35 2018 +0800

    eval: Restore input files in evalcommand

    When evalcommand invokes a command that modifies parsefile and
    then bails out without popping the file, we need to ensure the
    input file is restored so that the shell can continue to execute.

What I think it going on here, although I do not understand it completely yet, is:

evalcommand invokes a command that modifies parsefile: that's the dot command. The evaluation of the dotted file involves creating a subshell, and because of the invalid option, that subshell exits with EXERROR. Because the subshell is invoked from within the command builtin, that EXERROR is eaten, and the input file is restored. The subshell then happily continues reading commands at the same time as the parent shell.

Although this particular example used to work before that specific commit, I suspect the underlying problem had been there already and other examples could expose it just as well.

Fundamentally, I think an important question to ask is whether

  command . /dev/stdin <<EOF
  set -o invalid
  echo a
  EOF
  echo b

is supposed to abort the shell because of the invalid option, and if not, whether it should print a and b, or only b. Personally, I think there is nothing in POSIX to suggest that only b gets printed: either the special property of special built-in utilities that they cause the shell to exit on error apply, in which case nothing gets printed, or they do not apply, in which both a and b get printed. Nonetheless, printing b is the most popular result:

bash/yash/zsh print nothing.
dash/ksh/mksh/pdksh/posh print b.
bosh prints a and b.

My personal feeling is that "print nothing" is the correct result: the command built-in should only cause the immediately invoked command to not be treated as a special built-in utility, not anything indirectly invoked by that.

Cheers,
Harald van Dijk



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux