fix(zlib): 修正 out/buf 形参的联合类型写法,消除跨模块 ABI 错位
t.CUInt8T | t.CPtr[t.CPtr] 在定义侧按 PtrCount 累加得 i8**,但 stub/declare 侧(VpiReader 只把整段等于 t.CPtr/CPtr 的段认作 CPtr 标记)会坍缩为首段 i8,导致跨模块调用只传 1 字节、被调用方按 8 字节指针写入。ZlibTest 的 test_decompressobj 即由此触发 ASan heap-buffer-overflow:写入地址 = 压缩缓冲起址 -16(第 5 参栈槽残留的 compressed 指针被清零低字节) 改用 指针别名 | t.CPtr(两侧同为 i8**,与 win32sync.vp:65、posix.vp:199 同形),覆盖 zinflate_stream.decompress、zdeflate_stream.compress/flush、pyzlib.append_bytes 共 4 处;不改任何运行期逻辑
This commit is contained in:
1 parent
a9a53bd117
commit
794488b0f6
3 files changed
+19
-4
No files matched your search
+5
-1
@@ -484,7 +484,11 @@ def clone_bytes(pool: memhub.MemManager | t.CPtr, src: BYTEPTR, length: t.CSizeT
|
||||
if dst: string.memcpy(dst, src, length)
|
||||
return dst
|
||||
|
||||
def append_bytes(pool: memhub.MemManager | t.CPtr, buf: BYTE | t.CPtr[t.CPtr], length: t.CSizeT | t.CPtr, cap: t.CSizeT | t.CPtr,
|
||||
# buf 是"指针的指针"(i8**):不要写成 `BYTE | t.CPtr[t.CPtr]`——联合里嵌
|
||||
# `t.CPtr[...]` 下标时声明侧(StubGen/VpiReader)不认作 CPtr 标记,会坍缩成
|
||||
# 首段 BYTE = i8,与定义侧 i8** 不一致(跨模块调用即 ABI 错位,见
|
||||
# includes/zlib/zinflate.vp decompress 处说明)。改用"指针别名 | t.CPtr"。
|
||||
def append_bytes(pool: memhub.MemManager | t.CPtr, buf: BYTEPTR | t.CPtr, length: t.CSizeT | t.CPtr, cap: t.CSizeT | t.CPtr,
|
||||
data: BYTEPTR, data_len: t.CSizeT) -> t.CInt:
|
||||
if not data or data_len == 0: return 0
|
||||
needed: t.CSizeT = c.Deref(length) + data_len
|
||||
|
||||
+5
-2
@@ -166,8 +166,10 @@ class zdeflate_stream:
|
||||
def write_stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
|
||||
self.writer.stored_block(data, length, final)
|
||||
|
||||
# out 是"指针的指针"(i8**):见 zinflate.vp decompress 处的说明——
|
||||
# 联合里嵌 `t.CPtr[...]` 会让声明侧(VpiReader)坍缩成 i8,与定义侧 i8** 不一致。
|
||||
def compress(self, data: UINT8PTR, length: t.CSizeT,
|
||||
out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
out: BYTEPTR | t.CPtr, out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
if self.is_finished: return -2
|
||||
if not data or length == 0:
|
||||
c.Set(c.Deref(out), None)
|
||||
@@ -183,7 +185,8 @@ class zdeflate_stream:
|
||||
string.memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len))
|
||||
return 0
|
||||
|
||||
def flush(self, mode: t.CInt, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
# out 同 compress:i8**(声明侧/定义侧必须一致)。
|
||||
def flush(self, mode: t.CInt, out: BYTEPTR | t.CPtr, out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
if mode == 4:
|
||||
if not self.is_finished:
|
||||
if self.level == 0:
|
||||
|
||||
+9
-1
@@ -376,8 +376,16 @@ class zinflate_stream:
|
||||
self.input_pos += 4
|
||||
return 0
|
||||
|
||||
# out 是"指针的指针"(i8**)。不要写成 `t.CUInt8T | t.CPtr[t.CPtr]`:
|
||||
# 联合里嵌 `t.CPtr[...]` 下标时,定义侧按 PtrCount 累加得 i8**,而 stub/declare
|
||||
# 侧(StubGen/VpiReader)只把整段等于 `t.CPtr`/`CPtr` 的段认作 CPtr 标记,
|
||||
# 于是坍缩成首段 `t.CUInt8T` = i8 → 跨模块 ABI 不一致(调用方只传 1 字节,
|
||||
# 被调用方按 8 字节指针写入 → ASan heap-buffer-overflow)。
|
||||
# 改用"指针别名 | t.CPtr":两侧都按"追加 1 层指针"解析,同为 i8**。
|
||||
# 同形先例:includes/w32/win32sync.vp:65 `Context: VOIDPTR | t.CPtr`、
|
||||
# includes/posix.vp:199 `argv: CHARPTR | t.CPtr`。
|
||||
def decompress(self, data: UINT8PTR, length: t.CSizeT,
|
||||
max_length: t.CSizeT, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
max_length: t.CSizeT, out: BYTEPTR | t.CPtr, out_len: t.CSizeT | t.CPtr) -> t.CInt:
|
||||
if not self.is_initialized: return -2
|
||||
self.input_data = data
|
||||
self.input_len = length
|
||||
|
||||
Reference in new issue
Block a user