【问题标题】:strange zsh segfault glitch with function definitions带有函数定义的奇怪 zsh segfault 故障
【发布时间】:2015-11-10 21:22:40
【问题描述】:

我觉得这很整洁,但我参与的程度还不够,无法弄清楚发生了什么。

有谁知道为什么 zsh 中存在这种行为,或者 zsh 试图做什么导致段错误?

➜  ~  (echo "hi"(); echo "hi"; echo "hi")
[1]    65962 segmentation fault  ( echo "hi" () { ... }; echo "hi"; )

➜  ~  (ls(); ls; ls)
[1]    66073 segmentation fault  ( ls -G () { ... }; ls -G; )

我把它放在一个子进程中,以便它打印出发生了什么;否则,例如,如果你运行ls(),然后用ls 填写function>,然后再次运行ls,它会使终端崩溃。

仅当您尝试用自己重新定义函数时才会发生这种情况,例如 echo str1(); echo str2,而不是 ls(); echo str。它不适用于所有可能的输入,而仅仅是因为语法解析,例如,虽然:

➜  ~  (^A(); ^A; ^A)
[1]    66154 segmentation fault  ( ^A () { ... }; ^A; )

如果您逐行运行,由于语法原因,这不起作用:

➜  ~  ^A()
zsh: substitution failed

奇怪的是,会出现这样的行为:

➜  ~  a()
function> 7
➜  ~  a
a:cd:3: no such entry in dir stack
➜  ~  8()
function> b
➜  ~  8
cd:7: command not found: b
➜  ~  9()
function> 13
➜  ~  9
cd:6: command not found: 13

但是

➜  ~  9()
function> 5
➜  ~  (9)
[1]    66979 segmentation fault  ( cd -9; )

如果不在子进程中会导致终端崩溃,这意味着 您可以将一位数定义为指向两位数但不能指向一位数的函数 !这等效于字母(c(); a 是段错误制造者,c(); bh 是“未找到命令”)。 71(); 81; 71; 也不会导致段错误。

我很好奇引擎盖下出了什么问题!它确实提供了一种令人讨厌的与人相处的方式,因为把

echo $JAVA_HOME()
echo "hi" 

.zshrc 中即使有人只尝试使用 $JAVA_HOME 也会使终端崩溃,比如说,变量赋值,它会导致段错误,例如,

➜  ~  ($JAVA_HOME)
[1]    66745 segmentation fault  ( $JAVA_HOME; )    
➜  ~  (X= $JAVA_HOME)
[1]    66737 segmentation fault  ( X= $JAVA_HOME; )

也许这也需要一个补丁,因为我可以想象这可能会出于粗鲁的目的而被利用。这是一个已知问题吗?

由于 bash 解析函数定义的方式,它在 bash 中不起作用。

【问题讨论】:

  • (echo hi(); echo hi; echo hi) 的东西可能是一个错误,但关于单个数字和双数字:您的单个数字可能都别名为 cd +$digit(或 cd -$digit)。检查alias 1alias 2、...、alias 9,您会发现这是您的配置框架中的一个技巧(在 Prezto 中它位于 directory 中)。我仍然不清楚为什么会触发段错误;可能也是一个错误。向 zsh-workers@zsh.org 报告。
  • 你真的应该在 zs-workers@zsh.org 提交一个错误
  • 请注意,有一个段错误是一个错误。干净利落。如果语法错误或用户做了一些有趣的事情,shell 应该打印一个错误,而不是崩溃。

标签: unix terminal zsh zshrc oh-my-zsh


【解决方案1】:
➜  ~  (echo "hi"(); echo "hi"; echo "hi")
[1]    65962 segmentation fault  ( echo "hi" () { ... }; echo "hi"; )

➜  ~  (ls(); ls; ls)
[1]    66073 segmentation fault  ( ls -G () { ... }; ls -G; )

对于我的 zsh 这个打印

echo:1: maximum nested function level reached

ls:2: maximum nested function level reached

分别。



那么让我们来看看这些都在做什么。什么

echo "hi"(); echo "hi"; echo "hi"

实际上在做的是:

# Define functions "echo" and "hi" that will both execute the following code when called
function echo hi() {
    # These are what the function actually contains.  This means that inside of "echo," will be another "echo" that is calling the first echo with a (discarded) $1 of "hi."  Recursion!
    echo hi
}
# We haven't tripped up yet: we have yet to actually *call* this code.
echo "hi"
# And now we have.  Echo calls echo which calls echo, recursing too many times for zsh to handle.  This is known as "Stack Overflow," which is incidentally also the name of this site.

“ls”和“^A”的情况几乎相同。



➜  ~  a()
function> 7
➜  ~  a
a:cd:3: no such entry in dir stack
➜  ~  8()
function> b
➜  ~  8
cd:7: command not found: b
➜  ~  9()
function> 13
➜  ~  9
cd:6: command not found: 13

我不知道a() 定义是怎么回事,但其他所有的都完全正常。例如,您正在定义将调用命令“13”的函数“9”,而 zsh 抱怨没有名为“13”的命令,因此它没有任何事情可做。

➜  ~  9()
function> 5
➜  ~  (9)
[1]    66979 segmentation fault  ( cd -9; )

老实说,我不知道这个是怎么回事。您使用的是真正旧版本的 zsh 还是什么?作为其他阅读此线程的人的旁注,当我尝试定义此线程时,需要很长时间才能回到提示 - 这并没有发生在其他任何人身上,有人知道原因吗?

echo $JAVA_HOME()
echo "hi"

这与以前几乎相同。这将定义一个函数,可由“echo”或 $JAVA_HOME 的值调用,如果设置了将调用“echo”,将调用“echo”,将调用“echo”,我们的堆栈再次溢出。




希望能回答您的问题,如果您还有其他问题,请随时提问!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-08
    • 2020-08-03
    • 1970-01-01
    相关资源
    最近更新 更多