fix(HandlesAssign): 对"指针的指针"右值的自动解引用收窄为取地址形态

原判据只看右值的 LLVM 类型(Ptr(Ptr(...)))就 load 一层,于是显式 cast 的结果
(`entry = str*(uint64(argv) + idx*8)`,右值是 i8**)被多解一次引用 → 静默取到野指针
(includes/argparse.vp 的 parse_args 因此 ASan access-violation 0xffffffffffffffff)。

现限定为 Name/Attribute/Subscript 这类"取地址形态"(求值结果是存储地址,即"对象即指针"
返回 alloca/字段地址)才解引用;Call(显式 cast、构造/普通函数调用)与其它表达式给出的
是值本身,不再多解一层 —— 与 TransPyV 侧行为对齐(其 _deref_if_ptr_ptr 只用于字段访问
与调用分发,不在普通赋值路径)。
This commit is contained in:
TermiNexus committed 2026-10-01 18:33:21 +08:00
1 parent 2ba38ae842
commit 42c13e372b
1 file changed
+10 -2
+10 -2
View File
@@ -198,6 +198,14 @@ class AssignHandle(BaseHandle):
if isinstance(Value.type, ir.VoidType):
return
Gen._UnregisterTempPtr(Value)
# 【右值形态判定】只有"取地址形态"的右值才需要自动解一层引用:Name/Attribute/
# Subscript 的求值结果是**存储地址**(变量 alloca / 字段地址 /"对象即指针"),
# 赋给指针变量时必须 load 出内层指针。而 Call(显式 cast 如 `str*(addr)`、
# `t.CPtr(x)`,以及构造/普通函数调用)与其它表达式给出的是**值本身**,
# 再 load 会多解一层 → 静默取到野指针(现场 includes/argparse.vp 的
# `entry = str*(uint64(argv) + idx*8)`:i8** 右值被多解一次,entry 变成
# argv[idx] 本身,随后 entry[0] 去读字符串头 8 字节 → ASan access-violation)。
_rhs_addr_form: bool = isinstance(Node.value, (ast.Name, ast.Attribute, ast.Subscript))
# 大端局部变量:赋值时 bswap
Value = Gen._apply_bswap_if_big(Value, Gen.local_var_byteorders.get(VarName, ""), f"bswap_assign_{VarName}")
if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, (ir.LiteralStructType, ir.IdentifiedStructType)):
@@ -398,7 +406,7 @@ class AssignHandle(BaseHandle):
types_differ = TargetType and Value.type != TargetType
except AssertionError:
types_differ = False
if isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType):
if _rhs_addr_form and isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType):
LoadedValue: ir.Value = Gen._load(Value, name=f"Load_{VarName}")
Loaded_differ: bool
try:
@@ -435,7 +443,7 @@ class AssignHandle(BaseHandle):
GVar: ir.GlobalVariable = Gen.module.globals[VarName]
Gen._store(Value, GVar, Node=Node.value)
Gen.variables[VarName] = GVar
elif isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType):
elif _rhs_addr_form and isinstance(Value.type, ir.PointerType) and isinstance(Value.type.pointee, ir.PointerType):
LoadedValue: ir.Value = Gen._load(Value, name=f"Load_{VarName}")
var: ir.AllocaInstr = Gen._allocaEntry(LoadedValue.type, name=VarName)
Gen._store(LoadedValue, var, Node=Node.value)