fix(structgen): lookup_field SHA1 隔离改用 strncmp 前 16 字符比较,消除 stdlib.free 对 pool 子块的 bad-free(ASAN)

This commit is contained in:
TermiNexus committed 2026-08-26 23:58:07 +08:00
1 parent cc9112b54a
commit ee6d78bbb1
1 file changed
+13 -18
+13 -18
View File
@@ -711,29 +711,28 @@ class StructGenMixin:
ty_name: str = self._extract_struct_name(struct_ty)
if ty_name is not None:
# 加强 SHA1 命名空间隔离:类型名形如 "3d4afd9cdffeba6d.Thread",
# 提取 16 位 hex 前缀后精确匹配 entry.ModuleSha1,禁止 strstr 裸名
# 跨模块抓同名类(sched.Thread 被 includes/vthreading.vp 同名
# Thread 顶掉根因:strstr("sha1.Thread", "Thread") 命中 vthreading
# 的 entry → 其 arg@3 被当成 sched.Thread.arg(应 4)→ th.func
# 被 th.arg=None 覆盖 → _thread_entry call 0 → #UD/#GP)。
ty_sha1_lf: str = None
# 提取 16 位 hex 前缀与 entry.ModuleSha1 前 16 字符精确比较,
# 禁止 strstr 裸名跨模块抓同名类(sched.Thread 被 includes/
# vthreading.vp 同名 Thread 顶掉根因:strstr("sha1.Thread",
# "Thread") 命中 vthreading 的 entry → 其 arg@3 被当成
# sched.Thread.arg(应 4)→ th.func 被 th.arg=None 覆盖 →
# _thread_entry call 0 → #UD/#GP)。strncmp 不分配临时缓冲。
ty_has_sha1_lf: int = 0
dot_ty_lf: str = string.strchr(ty_name, '.')
if dot_ty_lf is not None:
pre_len_lf: t.CSizeT = t.CSizeT(
t.CUInt64T(dot_ty_lf) - t.CUInt64T(ty_name))
if pre_len_lf == 16:
sha_buf_lf: str = stdlib.malloc(17)
if sha_buf_lf is not None:
string.strncpy(sha_buf_lf, ty_name, 16)
sha_buf_lf[16] = '\0'
ty_sha1_lf = sha_buf_lf
ty_has_sha1_lf = 1
for i in range(self.StructCount):
entry: GenTypes.StructEntry | t.CPtr = self._get_struct_entry(i)
if entry is not None and entry.Name is not None:
# 提取到类型 SHA1:必须与 entry.ModuleSha1 精确一致,否则跳过
if ty_sha1_lf is not None:
# 类型名带 SHA1 前缀:必须与 entry.ModuleSha1 前 16 字符
# 精确一致,否则跳过(跨模块同名类命名空间隔离)
if ty_has_sha1_lf != 0:
if entry.ModuleSha1 is None \
or string.strcmp(entry.ModuleSha1, ty_sha1_lf) != 0:
or string.strlen(entry.ModuleSha1) < 16 \
or string.strncmp(entry.ModuleSha1, ty_name, 16) != 0:
continue
matched: int = 0
if string.strcmp(entry.Name, ty_name) == 0:
@@ -746,13 +745,9 @@ class StructGenMixin:
fe: GenTypes.FieldEntry | t.CPtr = self._get_field_entry(entry, fi)
if fe is not None and fe.Name is not None:
if string.strcmp(fe.Name, field_name) == 0:
if ty_sha1_lf is not None:
stdlib.free(ty_sha1_lf)
return fe
# 名称匹配但字段未找到,继续检查其他同名 entry(跨模块同名)
continue
if ty_sha1_lf is not None:
stdlib.free(ty_sha1_lf)
# 所有条目都未匹配
return None