Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

v0.12.0/v0.12.1 Linux release binaries SIGSEGV at startup on glibc 2.44 — bundled free() dereferences its segment table before init

未关闭
#2,763 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 2 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
48/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
c
领域
backend

调研方向

Start by inspecting the release build configuration and the allocator entry points described in the crash report; compare the v0.12.x startup path with v0.11.0. Reproduce with the Linux amd64 binary on glibc 2.44, then check whether --version and daemon start work after the fix. The issue also calls for checking allocator symbol visibility and adding a newest glibc release gate.

由索引模型根据 Issue 内容生成。

描述

bug editor/integration stability/performance ux/behavior

Summary

Both v0.12.0 and v0.12.1 Linux amd64 release assets die with SIGSEGV before printing anything,
on a host with current glibc (2.44). The v0.11.0 asset of the same shape runs normally. The process
never reaches main(): glibc's __newlocale calls free(NULL) during C++ locale static
initialization, that call is interposed to the executable's own bundled free(), and that free()
dereferences its segment table pointer unconditionally — which is still NULL at that point.

This affects the AUR -bin recipes too (they repack these assets), so Arch/Manjaro users upgrading
get a binary that cannot even answer --version.

Environment

OS Manjaro Linux, kernel 7.1.13-2-MANJARO x86_64
glibc 2.44+r24+g16be1518495f-1
libstdc++ / gcc-libs 16.2.1+r23+gd564253eb6c8-1
CPU Intel i9-9900K (no AVX-512, so a CPU-feature cause is ruled out)
Assets codebase-memory-mcp-linux-amd64.tar.gz, codebase-memory-mcp-ui-linux-amd64.tar.gz, v0.12.0 and v0.12.1

Reproduction

curl -fsSLO https://github.com/DeusData/codebase-memory-mcp/releases/download/v0.12.1/codebase-memory-mcp-ui-linux-amd64.tar.gz
sha512sum codebase-memory-mcp-ui-linux-amd64.tar.gz
# 54c9c05929c033e7e2635073397fe7167947399ab228fa3cfe4ca8acbd6b85d21e3ce383ebd34b65c0a46b7a5561fd01ca637e6d6dae85dad29b18de1990ab5b
tar -xf codebase-memory-mcp-ui-linux-amd64.tar.gz
./codebase-memory-mcp --version
Segmentation fault (core dumped)      # exit 139, no output

Same for --help, same for the v0.12.0 plain asset, same with env -i, same with LC_ALL=C LANG=C,
and same for a locally built AUR package from the same bytes — so this is not packaging, not the
environment, and not locale data. The v0.11.0 asset on the same host prints codebase-memory-mcp 0.11.0
and exits 0.

Crash

Signal: 11 (SEGV)   si_code: SEGV_MAPERR

#0  0x...5c952a5 free ()                                  <- INSIDE the executable
#1  0x7ffff763530a __newlocale () from /usr/lib/libc.so.6
#2  ... std::locale::facet::_S_create_c_locale (...)      from /usr/lib/libstdc++.so.6
#3  ... (libc.so.6)
#4  ... pthread_once ()                                   from /usr/lib/libc.so.6
#5  ... std::locale::facet::_S_get_c_locale ()
#6  ... std::ctype<char>::ctype (...)                     from /usr/lib/libstdc++.so.6
#7  ... std::locale::_Impl::_Impl (size_t)
#8  ... std::locale::locale ()
#9  ... std::ios_base::Init::Init ()
#10 ... (libstdc++.so.6)
#11 ... (ld-linux-x86-64.so.2)                            <- ELF init_array, before main

rip = 0x...5c952a5   rdi = 0x0   rsi = 0x0

rdi = 0 means the interposed free(NULL) is what kills it.

Mechanism

The release binary statically links its own libc and exports the allocator entry points in its
global dynamic symbol table:

readelf --dyn-syms ./codebase-memory-mcp | grep -E '__libc_(free|malloc|calloc|realloc|memalign)'
   372: 0000000000741290  173 FUNC GLOBAL DEFAULT 15 __libc_free
   385: 00000000007469c0  115 FUNC GLOBAL DEFAULT 15 __libc_memalign
   398: 0000000000744ef0   32 FUNC GLOBAL DEFAULT 15 __libc_realloc
   414: 0000000000744770   51 FUNC GLOBAL DEFAULT 15 __libc_calloc
   432: 00000000007442c0   25 FUNC GLOBAL DEFAULT 15 __libc_malloc

(and free itself at 0x741290). The executable is first in the global lookup scope, so when system
libstdc++.so.6 / libc.so.6 resolve free/__libc_free, they get the bundled copy.

glibc 2.44 frees a NULL temporary inside __newlocale. That call lands in the bundled allocator
before the allocator has any state:

0000000000741290 <free>:
  741290: f3 0f 1e fa           endbr64
  741294: 48 8b 05 e5 ad 51 13  mov    0x1351ade5(%rip),%rax   # 13c5c080   <- segment table ptr, still NULL
  74129b: 48 89 fa              mov    %rdi,%rdx
  74129e: 48 89 fe              mov    %rdi,%rsi
  7412a1: 48 c1 ea 1d           shr    $0x1d,%rdx             # segment index = ptr >> 29
  7412a5: 48 8b 14 d0           mov    (%rax,%rdx,8),%rdx     # <-- fault: load from NULL+0

In v0.11.0 the same exported symbol (free @ 0x4fccb0) loads no global pointer before it checks the
argument, so the identical free(NULL) from __newlocale is harmless — which is why only 0.12.x
breaks and why it looks environment-specific: it needs a system glibc that calls free(NULL) there
(2.44 does). Upstream CI on an older glibc would stay green.

Suggested fix

  1. Guard free(NULL) (and realloc(NULL, ·), __libc_free(NULL)) at the top of every allocator
    entry point
    , before any segment-table lookup. One compare-and-return fixes the crash.
  2. Stop exporting the libc allocator symbols as GLOBAL in .dynsym in the static release build
    (hidden/local visibility). That removes the interposition hazard permanently instead of relying on
    every path tolerating a foreign allocator.
  3. Add a release gate that runs <binary> --version (and daemon start) in a container on the
    newest glibc
    , not just on the build host's, so a startup regression cannot ship.

Impact / workaround for users

Every process dies before main(), so any MCP client (VS Code, Claude Code, Hermes, Codex, …) fails to
start the server, and --version, --help and install are all unusable. Until a fixed release:
stay on v0.11.0 (works), and pin it in the package manager.

主要语言
C
星标
45.8k
派生
3.8k
平均合并
3 天 4 小时
30 天内合并 PR
208

环境准备

这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

DeusData/codebase-memory-mcp 的其他 Issue

查看 DeusData/codebase-memory-mcp 的全部 Issue

相似的 Issue

更多 C Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。