diff --git a/lib/core/Handles/HandlesExprCall.py b/lib/core/Handles/HandlesExprCall.py index f857585..efdb796 100644 --- a/lib/core/Handles/HandlesExprCall.py +++ b/lib/core/Handles/HandlesExprCall.py @@ -2432,10 +2432,20 @@ class ExprCallHandle(BaseHandle): 有 vtable 的类 struct 首元素为 vtable 指针(i8*),class_members 不含它。 返回 None 表示无法计算(struct 未定义 / 字段不存在)。 """ + # class_members 的 key 是裸类名,而 ClassName 可能带 sha1 前缀 + # (跨模块 ObjVal 类型带前缀,如 "e1ea7eaf63a9c3d1.Generator")。 + # 不剥离则 members 为空 → 找不到字段 → this_adjust 被跳过 → 继承方法 + # self 不调整 → 运行时错位崩溃(register_reexport 写 0x3f 越界即此)。 + lookup_cls: str = ClassName + if len(ClassName) > 17 and ClassName[16] == '.': + lookup_cls = ClassName[17:] st = Gen.structs.get(ClassName) + if (not st or not isinstance(st, ir.IdentifiedStructType) or st.elements is None) \ + and lookup_cls != ClassName: + st = Gen.structs.get(lookup_cls) if not st or not isinstance(st, ir.IdentifiedStructType) or st.elements is None: return None - members: list = Gen.class_members.get(ClassName, []) + members: list = Gen.class_members.get(lookup_cls, []) has_vtable: bool = (ClassName in Gen.class_vtable or ClassName in Gen._cross_module_vtable_classes) base: int = 1 if has_vtable else 0 @@ -2493,7 +2503,10 @@ class ExprCallHandle(BaseHandle): """ if method_anc is None or method_anc == ClassName: return ObjVal - anc_members: list = Gen.class_members.get(method_anc, []) + anc_lookup: str = method_anc + if len(method_anc) > 17 and method_anc[16] == '.': + anc_lookup = method_anc[17:] + anc_members: list = Gen.class_members.get(anc_lookup, []) if not anc_members: return ObjVal first_field_name: str | None = None @@ -3289,15 +3302,52 @@ class ExprCallHandle(BaseHandle): attr_name = arg_node.attr len_member = f'{attr_name}__len' current_class = self.Trans._CurrentCpythonObjectClass - if current_class and current_class in Gen.class_members: - for m_name, m_type in Gen.class_members[current_class]: + # 关键:_CurrentCpythonObjectClass 可能带 sha1 前缀(如 + # 'a351387236c6ce1c.TypeGenCType'),而 class_members / + # class_member_element_class 的 key 全部是裸类名。必须先把前缀剥离 + # 再做 `in Gen.class_members` 检查——否则带前缀时 gate 直接 miss, + # 整个 self.attr 分支(含 list.__len__ 修复)被跳过,fall through + # 到 strlen(stdint.vp 0xC0000005 崩溃根因)。 + bare_cls: str | None = current_class + if bare_cls and len(bare_cls) > 17 and bare_cls[16] == '.': + bare_cls = bare_cls[17:] + if bare_cls and bare_cls in Gen.class_members: + for m_name, m_type in Gen.class_members[bare_cls]: if m_name == len_member: self_val = Gen._get_var_ptr('self') if self_val: self_ptr = Gen._load(self_val, name="self_for_len") - offset = Gen._get_member_offset(len_member, current_class) + offset = Gen._get_member_offset(len_member, bare_cls) len_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"self_{len_member}_ptr") return Gen._load(len_ptr, name=f"self_{len_member}") + # 修复 stdint.vp 崩溃(0xC0000005)根因:`list[X] | t.CPtr` 联合字段 + # 的 LLVM 类型退化为 i8*,_HandleLenLlvm 无法识别为 list,fall through + # 到 strlen 分支 → 对 list 对象指针执行 strlen → 垃圾长度 → 越界 get + # → 垃圾指针 → strcmp 崩。此处按字段静态类型(class_member_element_class + # 记录的特化名,如 'list[str]',沿 MRO 链查找含父类)分派到 list.__len__。 + field_cls: str | None = None + _elem_map: dict = getattr(Gen, 'class_member_element_class', {}) + for _mro_cls in Gen._get_mro_chain(bare_cls): + # class_member_element_class 的 key 是裸类名(如 'TypeGenBase'), + # _get_mro_chain 在输入裸名时也返回裸名链;再保险剥一次前缀。 + _mro_key: str = _mro_cls + if len(_mro_cls) > 17 and _mro_cls[16] == '.': + _mro_key = _mro_cls[17:] + _sub: dict = _elem_map.get(_mro_key, {}) + if attr_name in _sub: + field_cls = _sub[attr_name] + break + if field_cls and (field_cls == 'list' or field_cls.startswith('list[')): + self_val = Gen._get_var_ptr('self') + if self_val: + self_ptr = Gen._load(self_val, name="self_for_len") + offset = Gen._get_member_offset(attr_name, bare_cls) + if offset is not None: + list_ptr = Gen.builder.gep(self_ptr, [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), offset)], name=f"self_{attr_name}_ptr") + list_val = Gen._load(list_ptr, name=f"self_{attr_name}") + result = self.Trans.ExprUtils._try_operator_overLoad(field_cls, '__len__', list_val, Gen) + if result is not None: + return result val = self.HandleExprLlvm(arg_node) if not val: return None