fix(core): 数组下标 <32 位索引 zext 到 i32,修复字节索引越界

This commit is contained in:
TermiNexus committed 2026-08-07 22:36:28 +08:00
1 parent d6690c6e39
commit 7d6917762c
1 file changed
+28 -4
+28 -4
View File
@@ -191,6 +191,26 @@ def is_array_type(ty: llvmlite.LLVMType | t.CPtr) -> int:
return 0
# ============================================================
# _zext_index_to_i32 - 数组下标索引零扩展
#
# LLVM GEP 对窄整数索引默认符号扩展:i8 0xE2(226) 会被当成 -30,
# 导致数组下标越界读(字节 >= 128 的乱码根因)。
# 数组下标语义为非负,<32 位整数索引一律 zext 到 i32。
# 仅用于数组 GEP;指针负偏移(p[-1])不经过此路径,不受影响。
# ============================================================
def _zext_index_to_i32(builder: llvmlite.IRBuilder | t.CPtr,
idx_val: llvmlite.Value | t.CPtr) -> llvmlite.Value | t.CPtr:
"""将 <32 位整数下标零扩展到 i32(数组下标非负语义)"""
if idx_val is None or idx_val.Ty is None or builder is None:
return idx_val
idx_bits: int = get_llvm_type_bits(idx_val.Ty)
if idx_bits != 0 and idx_bits < 32:
i32_ty: llvmlite.LLVMType | t.CPtr = llvmlite.Int32(builder.Pool)
return llvmlite.build_zext(builder, idx_val, i32_ty)
return idx_val
# ============================================================
# _get_custom_struct_cls_nm - 检查类型是否为已注册的自定义结构体
#
@@ -2268,7 +2288,8 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
case llvmlite.LLVMType.Array(elem_ty, count):
# 数组遍历: getelementptr [N x elem_ty], ... , i32 0, i32 %idx
elem_ptr: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca, idx_val)
builder, pointee, elem_ty, alloca,
_zext_index_to_i32(builder, idx_val))
if elem_ptr is not None:
return llvmlite.build_load(builder, elem_ty, elem_ptr)
return None
@@ -2388,7 +2409,8 @@ def translate_subscript(builder: llvmlite.IRBuilder | t.CPtr,
match elem_ty2:
case llvmlite.LLVMType.Array(arr_elem_ty2, arr_count2):
elem_ptr3: llvmlite.Value | t.CPtr = llvmlite.build_gep_array(
builder, elem_ty2, arr_elem_ty2, ptr_val, idx_val)
builder, elem_ty2, arr_elem_ty2, ptr_val,
_zext_index_to_i32(builder, idx_val))
if elem_ptr3 is not None:
return llvmlite.build_load(builder, arr_elem_ty2, elem_ptr3)
return None
@@ -3065,7 +3087,8 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
case llvmlite.LLVMType.Array(elem_ty, count):
# 数组遍历
return llvmlite.build_gep_array(
builder, pointee, elem_ty, alloca, idx_val)
builder, pointee, elem_ty, alloca,
_zext_index_to_i32(builder, idx_val))
case llvmlite.LLVMType.Ptr(inner_ty):
# inner_ty 是 Ptr 说明 alloca.Ty 是三重指针,
# 即 X|t.CPtr 当 X 本身是指针类型 (如 T=AST|t.CPtr, T|t.CPtr=AST**)。
@@ -3120,7 +3143,8 @@ def get_subscript_ptr(builder: llvmlite.IRBuilder | t.CPtr,
match elem_ty2:
case llvmlite.LLVMType.Array(arr_elem_ty, arr_count):
return llvmlite.build_gep_array(
builder, elem_ty2, arr_elem_ty, ptr_val, idx_val)
builder, elem_ty2, arr_elem_ty, ptr_val,
_zext_index_to_i32(builder, idx_val))
case _:
pass
# 自定义结构体 (如 self._ht[key]): 返回 None,