提问人:charmoniumQ 提问时间:9/23/2023 最后编辑:charmoniumQ 更新时间:9/23/2023 访问量:46
当 LC_CTYPE 设置为 C.UTF-8 时,Bash 在 Valgrind 中崩溃
Bash crashes in Valgrind when LC_CTYPE is set to C.UTF-8
问:
Bash 5.2 由于 malloc 中的断言失败而崩溃,但仅在 Valgrind 中运行时且仅在设置时崩溃。下面是一个示例输出:LC_CTYPE
$ path/to/env - foo=bar LC_CTYPE=C.UTF-8 path/to/valgrind path/to/bash -c 'echo ${foo#spam}'
...
malloc: subst.c:5331: assertion botched
free: called with unallocated block argument
Aborting...==2753214==
==2753214== Process terminating with default action of signal 6 (SIGABRT): dumping core
==2753214== at 0x48DFA8C: __pthread_kill_implementation (in /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libc.so.6)
==2753214== by 0x4890C85: raise (in /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libc.so.6)
==2753214== by 0x487A8B9: abort (in /nix/store/aw2fw9ag10wr9pf0qk4nk5sxi0q0bn56-glibc-2.37-8/lib/libc.so.6)
==2753214== by 0x443AF9: programming_error (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x4ACAC4: internal_free.constprop.0 (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x450A5E: remove_pattern (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x465D2B: parameter_brace_remove_pattern (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x46023A: param_expand (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x460CD9: expand_word_internal (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x466C0D: shell_expand_word_list.constprop.0 (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x467479: expand_words (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
==2753214== by 0x4361CE: execute_command_internal (in /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash)
...
==2753214== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
/nix/store/a683qmhmrrzrwn8fmqh53yyylm7yn2hq-test.sh: line 2: 2753214 Aborted (core dumped) /nix/store/v45j2p2izb3pa2fxdw978bahhkb2ghza-toybox-0.8.10/bin/env - LC_CTYPE=C.UTF-8 /nix/store/14fg82n6grqhrd2algx31sv1kmgvz0gl-valgrind-3.21.0/bin/valgrind /nix/store/vqvj60h076bhqj6977caz0pfxs6543nb-bash-5.2-p15/bin/bash -c 'echo ${PATH#":"}'
(完整输出在这里)
${parameter#word}
是这里描述的一种参数扩展。
指示的源代码行指向此处,但有问题的断言是否在 or ?free
malloc
尝试一些变化:
- 在 Valgrind 之外,Bash 成功了(根本不崩溃)。
- 保留 unset 或设置为 empty-string 会导致 Bash 成功(无崩溃);但是任何非空设置似乎都会导致崩溃。
foo
foo
- 如果我们将该模式替换为 中确实存在的模式,则 Bash 崩溃,而不是 ;这两种情况都会导致崩溃,当模式与参数扩展匹配时,当它不匹配时,但在略有不同的位置。
foo
subst.c:5336
subst.c:5331
- 当未设置或设置为任何其他语言环境(包括不存在的语言环境)时,Bash 不会崩溃(尽管存在非致命无效)。
LC_CTYPE
free()
我应该如何调试此问题?
关于可重复性的说明:
- 因为我没有使用默认系统中的任何环境变量、二进制文件或库,所以我认为这在任何x86_64机器上都应该相当可重现。如果重要的话,我在 Linux 5.15.0-83-generic 上运行 Ubuntu 22.04.3。
- 我在这里创建了一个 Nix 薄片。如果您下载并下载到一个空目录,您应该能够键入并(希望)也崩溃。
flake.nix
flake.lock
nix run
答:
我会创建一个特殊的 Bash 版本,其中禁用了 Bash 的 malloc 包装,并尝试像以前一样在 Valgrind 下重现该问题。
您遇到了 Bash 本身正在自我诊断 malloc 问题的问题。它不会像 Valgrind 本身那样做得好。
Bash 的诊断是说它是在未分配的块上调用的。Valgrind 的类似诊断信息量更大。如果之前在该地址存在已分配的对象,Valgrind 将显示该对象,以及释放该对象的位置的回溯跟踪。free
Bash 的调试 malloc(参见 中的函数依赖于检查 freed 块中的一些标头信息来得出结论,它是双重释放的。这是不准确的。代码如下所示:internal_free
lib/malloc/malloc.c
if (p->mh_alloc != ISALLOC)
{
if (p->mh_alloc == ISFREE)
xbotch (mem, ERR_DUPFREE,
_("free: called with already freed block argument"), file, line);
else
xbotch (mem, ERR_UNALLOC,
_("free: called with unallocated block argument"), file, line);
}
如果在块头中发现一个魔术字节,而该魔术字节不是 (即 ),它会专门检查 .如果不是 (),则它会发出您看到的诊断。ISALLOC
0xF7
ISFREE
ISFREE
0x57
这很容易出现误报,因为当标头中的魔术代码被破坏为不是 256 个可能值中的两个可能值之一的值时,就会发生误报。
我们不能合理地认为这是一个双重自由问题。这很可能是腐败,如果它重现,Valgrind 的分配器在诊断它方面会做得更好。
评论
C.UTF-8