dash:当我的脚本甚至不包含反引号时,为什么我会收到错误“语法错误:反引号替换中的 EOF”?

dash:当我的脚本甚至不包含反引号时,为什么我会收到错误“语法错误:反引号替换中的 EOF”?
#!/bin/sh --

for set_trap_sig in HUP INT QUIT ALRM TERM; do
    trap -- '
        trap -- - '"${set_trap_sig:?}"' EXIT || exit "$?"
        kill -s '"${set_trap_sig:?}"' -- "$$" || exit "$?"' "$set_trap_sig"
done

sleep 15 || exit "$?"

这是我向脚本发送 SIGINT 时发生的情况

user@hostname:/tmp$ ./script.sh
^C./script.sh: 3: ./script.sh: Syntax error: EOF in backquote substitution

这个问题似乎是针对 dash 的。在 ash、bash 和 ksh93 上我没有收到此错误。这特别奇怪,因为我的脚本甚至不包含反引号字符。

如果我删除第 5 行末尾的双引号,$?错误就会消失。

我是在做一些愚蠢的事情还是dash行为不当?请不要对我的脚本中的错误检查级别发表评论。

我们现在已经确定这是一个非常严重的错误,甚至影响现代版本的 Ubuntu 和 Debian。有谁知道解决方法?

答案1

这是一个简化的测试用例:

trap '
        trap    - HUP EXIT || exit "$?"
        kill -s HUP    "$$" || exit "$?" ' HUP INT
kill -HUP $$
$ dash dash-bug
dash-bug: 3: /home2/ahq/dash-bug: Syntax error: EOF in backquote substitution

修改引用代码的长度或内容可能会“修复”错误或产生不同且有趣的损坏,随机字节会突然出现。

这是由释放后使用错误引起的,该错误自 dash 0.5.9 起已修复,但在 Debian 9.8 stable (stretch)、Ubuntu 18.04 (bionic) 和 Ubuntu 18.10 (cosmic) 的 dash 0.5.8 中仍然存在。

这是犯罪修复了它:

commit 6c3f73bc536082fec38bd36e6c8a121033c68835
Author: Herbert Xu <[email protected]>
Date:   Thu Oct 2 08:26:06 2014 +0800

    [EVAL] Fix use-after-free in dotrap/evalstring

    The function dotrap calls evalstring using the stored trap string.
    If evalstring then unsets that exact trap string then we will end
    up using freed memory.

    This patch fixes it by making evalstring always duplicate the string
    before using it.

    Signed-off-by: Herbert Xu <[email protected]>

解决方法是将陷阱处理程序放入函数中 - 以便在陷阱取消设置后不会运行任何命令,并在释放后尝试使用操作字符串:

sighandler(){
    trap - "$sig" EXIT || exit "$?"
    kill -s "$sig" "$$" || exit "$?"
}
for sig in HUP INT QUIT ALRM TERM; do
    trap "sig=$sig; sighandler" "$sig"
done

kill -s HUP "$$"

相关内容