修正了一些错误

This commit is contained in:
2026-07-20 11:13:23 +08:00
parent a557718ba5
commit 6eb3d22eba
9 changed files with 2921 additions and 6 deletions

View File

@@ -171,6 +171,7 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE) bytes_read: t.CInt64T = f.read_all(buf, BUF_SIZE)
f.close() f.close()
if bytes_read <= 0: if bytes_read <= 0:
stdlib.free(buf)
return None return None
# 原地去除 \rCRLF → LF与 Projectrans.py 文本模式读取一致 # 原地去除 \rCRLF → LF与 Projectrans.py 文本模式读取一致
@@ -189,17 +190,21 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
# 计算 SHA1 # 计算 SHA1
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1() ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
if ctx is None: if ctx is None:
stdlib.free(buf)
return None return None
ctx.update(buf) ctx.update(buf)
digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN) digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN)
if digest is None: if digest is None:
stdlib.free(buf)
return None return None
ctx.final(digest) ctx.final(digest)
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符) # 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
hex_buf: str = stdlib.malloc(17) hex_buf: str = stdlib.malloc(17)
if hex_buf is None: if hex_buf is None:
stdlib.free(buf)
stdlib.free(digest)
return None return None
for i in range(8): for i in range(8):
hi: int = (digest[i] >> 4) & 0xF hi: int = (digest[i] >> 4) & 0xF
@@ -213,6 +218,9 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
else: else:
hex_buf[i * 2 + 1] = 'a' + (lo - 10) hex_buf[i * 2 + 1] = 'a' + (lo - 10)
hex_buf[16] = '\0' hex_buf[16] = '\0'
# 释放临时缓冲区hex_buf 由调用者负责释放)
stdlib.free(buf)
stdlib.free(digest)
return hex_buf return hex_buf
@@ -245,6 +253,8 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data) handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
if handle == win32base.INVALID_HANDLE_VALUE: if handle == win32base.INVALID_HANDLE_VALUE:
stdlib.free(pattern)
stdlib.free(find_data)
return 1 return 1
# 遍历所有文件和子目录 # 遍历所有文件和子目录
@@ -284,6 +294,7 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
prefix_len = string.strlen(rel_prefix) prefix_len = string.strlen(rel_prefix)
rel_path: bytes = stdlib.malloc(prefix_len + fname_len + 2) rel_path: bytes = stdlib.malloc(prefix_len + fname_len + 2)
if rel_path is None: if rel_path is None:
stdlib.free(full_path)
break break
if rel_prefix is not None and prefix_len > 0: if rel_prefix is not None and prefix_len > 0:
viperlib.snprintf(rel_path, prefix_len + fname_len + 2, "%s/%s", rel_prefix, fname) viperlib.snprintf(rel_path, prefix_len + fname_len + 2, "%s/%s", rel_prefix, fname)
@@ -312,13 +323,21 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
sha1: str = compute_file_sha1(pool, full_path) sha1: str = compute_file_sha1(pool, full_path)
if sha1 is not None: if sha1 is not None:
add_file_entry(result, pool, full_path, rel_path, sha1) add_file_entry(result, pool, full_path, rel_path, sha1)
stdio.printf(" [scan] %s -> %s\n", rel_path, sha1) # 释放 compute_file_sha1 返回的临时 hex_buf
stdlib.free(sha1)
# 释放本次迭代分配的路径缓冲区
stdlib.free(full_path)
stdlib.free(rel_path)
# 继续搜索下一个文件 # 继续搜索下一个文件
if win32file.FindNextFileA(handle, find_data) == 0: nxt: t.CInt = win32file.FindNextFileA(handle, find_data)
if nxt == 0:
break break
win32file.FindClose(handle) win32file.FindClose(handle)
stdlib.free(pattern)
stdlib.free(find_data)
return 0 return 0
@@ -341,7 +360,8 @@ def scan_includes(pool: memhub.MemBuddy | t.CPtr,
scan_directory_recursive(pool, includes_dir, None, result) scan_directory_recursive(pool, includes_dir, None, result)
stdio.printf("[Phase1] 扫描完成: %d 个 .py 文件\n", result.Count) count: t.CInt = result.Count
stdio.printf("[Phase1] 扫描完成: %d 个 .py 文件\n", count)
return result return result

View File

@@ -44,47 +44,78 @@ SRC_BUF_SIZE: t.CDefine = 1048576
def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str, def RunPhase1(mb: memhub.MemBuddy | t.CPtr, includes_dir: str, temp_dir: str,
log: VLogger.Logger | t.CPtr) -> int: log: VLogger.Logger | t.CPtr) -> int:
"""Phase1: 扫描 includes 目录,按需翻译并生成 stub""" """Phase1: 扫描 includes 目录,按需翻译并生成 stub"""
stdio.printf("[P1 ENTER] mb=%p inc=%p temp=%p log=%p\n", mb, includes_dir, temp_dir, log)
stdio.fflush(0)
if includes_dir is None or temp_dir is None: if includes_dir is None or temp_dir is None:
stdio.printf("[Phase1] includes_dir 或 temp_dir 为空,跳过\n") stdio.printf("[Phase1] includes_dir 或 temp_dir 为空,跳过\n")
return 1 return 1
stdio.printf("[P1] before log.banner\n")
stdio.fflush(0)
if log is not None: if log is not None:
log.banner("Phase1: 扫描 includes按需翻译") log.banner("Phase1: 扫描 includes按需翻译")
stdio.printf("[P1] after log.banner\n")
stdio.fflush(0)
# 扫描 includes 目录 # 扫描 includes 目录
stdio.printf("[P1] before scan_includes: mb=%p inc=%s\n", mb, includes_dir)
stdio.fflush(0)
result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir) result: IncludesScanner.ScanResult | t.CPtr = IncludesScanner.scan_includes(mb, includes_dir)
stdio.printf("[P1] after scan_includes: result=%p\n", result)
stdio.fflush(0)
if result is None: if result is None:
stdio.printf("[Phase1] 扫描失败\n") stdio.printf("[Phase1] 扫描失败\n")
return 1 return 1
stdio.printf("[Phase1] 共 %d 个文件\n", result.Count) stdio.printf("[P1] result.Count=%d\n", result.Count)
stdio.fflush(0)
# 读取 _sha1_map.txt 获取需要的 includes SHA1 集合 # 读取 _sha1_map.txt 获取需要的 includes SHA1 集合
# 优先使用 Projectrans.py 生成的 _sha1_map.txt含依赖分析只包含需要的 includes
# 若不存在,则从扫描结果生成(包含所有 includes可能导致结构体表溢出
sha1_set: str = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17) sha1_set: str = stdlib.malloc(StubMerger.MAX_INCLUDES_SHA1 * 17)
stdio.printf("[P1] sha1_set=%p\n", sha1_set)
stdio.fflush(0)
if sha1_set is None: if sha1_set is None:
stdio.printf("[Phase1] sha1_set 分配失败\n") stdio.printf("[Phase1] sha1_set 分配失败\n")
return 1 return 1
string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17) string.memset(sha1_set, 0, StubMerger.MAX_INCLUDES_SHA1 * 17)
stdio.printf("[P1] before _load_includes_sha1_set\n")
stdio.fflush(0)
set_count: int = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set) set_count: int = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set)
stdio.printf("[P1] set_count=%d\n", set_count)
stdio.fflush(0)
if set_count <= 0: if set_count <= 0:
stdio.printf("[Phase1] _sha1_map.txt 不存在或为空,从扫描结果生成\n") stdio.printf("[Phase1] _sha1_map.txt 不存在或为空,从扫描结果生成\n")
stdio.fflush(0)
stdio.printf("[P1] before WriteIncludesSha1Map\n")
stdio.fflush(0)
StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, None, 0) StubMerger.WriteIncludesSha1Map(mb, temp_dir, result, None, 0)
stdio.printf("[P1] after WriteIncludesSha1Map, before _load_includes_sha1_set\n")
stdio.fflush(0)
set_count = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set) set_count = StubMerger._load_includes_sha1_set(mb, temp_dir, sha1_set)
stdio.printf("[P1] set_count2=%d\n", set_count)
stdio.fflush(0)
if set_count < 0: if set_count < 0:
stdio.printf("[Phase1] 无法加载 _sha1_map.txt跳过 Phase1\n") stdio.printf("[Phase1] 无法加载 _sha1_map.txt跳过 Phase1\n")
return 1 return 1
stdio.printf("[Phase1] includes SHA1 集合: %d\n", set_count) stdio.printf("[Phase1] includes SHA1 集合: %d\n", set_count)
stdio.fflush(0)
# 构建模块 SHA1 映射(供跨模块函数调用名混淆使用) # 构建模块 SHA1 映射(供跨模块函数调用名混淆使用)
td_len_p1map: t.CSizeT = string.strlen(temp_dir) td_len_p1map: t.CSizeT = string.strlen(temp_dir)
p1_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17) p1_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
p1_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64) p1_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
p1_inc_count: int = 0 p1_inc_count: int = 0
stdio.printf("[P1] before _BuildIncludesSha1Map\n")
stdio.fflush(0)
if p1_sha1_arr is not None and p1_mod_arr is not None: if p1_sha1_arr is not None and p1_mod_arr is not None:
p1_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_p1map, p1_sha1_arr, p1_mod_arr) p1_inc_count = StubMerger._BuildIncludesSha1Map(temp_dir, td_len_p1map, p1_sha1_arr, p1_mod_arr)
stdio.printf("[P1] after _BuildIncludesSha1Map: inc=%d\n", p1_inc_count)
stdio.fflush(0)
stdio.printf("[P1] before set_module_sha1_map\n")
stdio.fflush(0)
HandlesExprCall.set_module_sha1_map(p1_sha1_arr, p1_mod_arr, p1_inc_count) HandlesExprCall.set_module_sha1_map(p1_sha1_arr, p1_mod_arr, p1_inc_count)
stdio.printf("[P1] after set_module_sha1_map\n")
stdio.fflush(0)
# 初始化 AST 表(只需一次) # 初始化 AST 表(只需一次)
ast._init_tables(mb) ast._init_tables(mb)

View File

@@ -8,6 +8,7 @@ import llvmlite
import w32.win32file as win32file import w32.win32file as win32file
import w32.win32base as win32base import w32.win32base as win32base
import w32.fileio as fileio import w32.fileio as fileio
import w32.win32memory as win32memory
import viperlib import viperlib
import sys import sys
import ast import ast
@@ -69,6 +70,7 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.R) f: fileio.File | t.CPtr = fileio.File(map_path, fileio.MODE.R)
if f.closed: if f.closed:
stdio.printf("[StubMerger] _sha1_map.txt 不存在: %s\n", map_path) stdio.printf("[StubMerger] _sha1_map.txt 不存在: %s\n", map_path)
stdlib.free(map_path)
return -1 return -1
# 读取内容(使用 stdlib.malloc 避免 mbuddy 池耗尽) # 读取内容(使用 stdlib.malloc 避免 mbuddy 池耗尽)
@@ -76,10 +78,13 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
content: str = stdlib.malloc(MAP_BUF_SIZE) content: str = stdlib.malloc(MAP_BUF_SIZE)
if content is None: if content is None:
f.close() f.close()
stdlib.free(map_path)
return -1 return -1
bytes_read: t.CInt64T = f.read_all(content, MAP_BUF_SIZE) bytes_read: t.CInt64T = f.read_all(content, MAP_BUF_SIZE)
f.close() f.close()
stdlib.free(map_path)
if bytes_read <= 0: if bytes_read <= 0:
stdlib.free(content)
return -1 return -1
content[bytes_read] = '\0' content[bytes_read] = '\0'
@@ -112,6 +117,7 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
sha1_set[count * 17 + 16] = '\0' sha1_set[count * 17 + 16] = '\0'
count += 1 count += 1
stdlib.free(content)
return count return count
@@ -189,6 +195,8 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
written_count += 1 written_count += 1
f.close() f.close()
stdlib.free(map_path)
stdlib.free(line_buf)
stdio.printf("[Phase1] 已写入 _sha1_map.txt (%d 个 includes)\n", written_count) stdio.printf("[Phase1] 已写入 _sha1_map.txt (%d 个 includes)\n", written_count)
return 0 return 0
@@ -735,14 +743,32 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
map_buf[map_br] = '\0' map_buf[map_br] = '\0'
else: else:
map_buf[STUB_READ_BUF_SIZE - 1] = '\0' map_buf[STUB_READ_BUF_SIZE - 1] = '\0'
stdio.printf("[BISM] map_br=%lld\n", map_br)
stdio.fflush(0)
# 堆探针:测试堆是否已被之前的操作损坏
probe: bytes = stdlib.malloc(17)
stdio.printf("[BISM] probe malloc(17)=%p\n", probe)
stdio.fflush(0)
if probe is not None:
stdlib.free(probe)
stdio.printf("[BISM] probe free OK\n")
stdio.fflush(0)
count: int = 0 count: int = 0
pos: t.CSizeT = 0 pos: t.CSizeT = 0
while pos < map_br and count < MAX_INCLUDES: while pos < map_br and count < MAX_INCLUDES:
stdio.printf("[BISM] iter=%d pos=%d\n", count, pos)
stdio.fflush(0)
# 提取 SHA116 hex # 提取 SHA116 hex
sha1: t.CChar | t.CPtr = stdlib.malloc(17) sha1: t.CChar | t.CPtr = stdlib.malloc(17)
stdio.printf("[BISM] malloc(17)=%p\n", sha1)
stdio.fflush(0)
if sha1 is None: if sha1 is None:
break break
hv: int = win32memory.HeapValidate(win32memory.GetProcessHeap(), 0, None)
stdio.printf("[BISM] HV after malloc(sha1)=%d\n", hv)
stdio.fflush(0)
string.strncpy(sha1, map_buf + pos, 16) string.strncpy(sha1, map_buf + pos, 16)
sha1[16] = '\0' sha1[16] = '\0'
pos += 16 pos += 16
@@ -755,6 +781,8 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
while pos < map_br and map_buf[pos] != '\n' and map_buf[pos] != '\r' and map_buf[pos] != '\0': while pos < map_br and map_buf[pos] != '\n' and map_buf[pos] != '\r' and map_buf[pos] != '\0':
pos += 1 pos += 1
path_len: t.CSizeT = pos - path_start path_len: t.CSizeT = pos - path_start
stdio.printf("[BISM] path_len=%d\n", path_len)
stdio.fflush(0)
# 跳过 \r\n 或 \n # 跳过 \r\n 或 \n
if pos < map_br and map_buf[pos] == '\r': if pos < map_br and map_buf[pos] == '\r':
pos += 1 pos += 1
@@ -765,25 +793,49 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
# 否则用户文件会被误判为 includes导致 is_module_imported 模块名不匹配而跳过加载 # 否则用户文件会被误判为 includes导致 is_module_imported 模块名不匹配而跳过加载
if path_len >= 9 and string.strncmp(map_buf + path_start, "includes/", 9) == 0: if path_len >= 9 and string.strncmp(map_buf + path_start, "includes/", 9) == 0:
path_buf: t.CChar | t.CPtr = stdlib.malloc(path_len + 1) path_buf: t.CChar | t.CPtr = stdlib.malloc(path_len + 1)
stdio.printf("[BISM] malloc(%d)=%p\n", path_len + 1, path_buf)
stdio.fflush(0)
if path_buf is not None: if path_buf is not None:
string.strncpy(path_buf, map_buf + path_start, path_len) string.strncpy(path_buf, map_buf + path_start, path_len)
path_buf[path_len] = '\0' path_buf[path_len] = '\0'
hv2: int = win32memory.HeapValidate(win32memory.GetProcessHeap(), 0, None)
stdio.printf("[BISM] HV after fill(path_buf)=%d\n", hv2)
stdio.fflush(0)
mod_name: str = _PathToModuleName(path_buf) mod_name: str = _PathToModuleName(path_buf)
stdio.printf("[BISM] _PathToModuleName=%p\n", mod_name)
stdio.fflush(0)
hv3: int = win32memory.HeapValidate(win32memory.GetProcessHeap(), 0, None)
stdio.printf("[BISM] HV after _PathToModuleName=%d\n", hv3)
stdio.fflush(0)
stdlib.free(path_buf) stdlib.free(path_buf)
if mod_name is not None: if mod_name is not None:
# 存储 sha1 和 mod_name 到数组中 # 存储 sha1 和 mod_name 到数组中
idx: t.CSizeT = t.CSizeT(count) * 17 idx: t.CSizeT = t.CSizeT(count) * 17
string.strcpy(sha1_list + idx, sha1) string.strcpy(sha1_list + idx, sha1)
hv4: int = win32memory.HeapValidate(win32memory.GetProcessHeap(), 0, None)
stdio.printf("[BISM] HV after strcpy(sha1_list)=%d\n", hv4)
stdio.fflush(0)
idx2: t.CSizeT = t.CSizeT(count) * 64 idx2: t.CSizeT = t.CSizeT(count) * 64
mn_len: t.CSizeT = string.strlen(mod_name) mn_len: t.CSizeT = string.strlen(mod_name)
stdio.printf("[BISM] mn_len=%d count=%d\n", mn_len, count)
stdio.fflush(0)
if mn_len < 64: if mn_len < 64:
string.strcpy(mod_list + idx2, mod_name) string.strcpy(mod_list + idx2, mod_name)
else: else:
string.strncpy(mod_list + idx2, mod_name, 63) string.strncpy(mod_list + idx2, mod_name, 63)
mod_list[idx2 + 63] = '\0' mod_list[idx2 + 63] = '\0'
hv5: int = win32memory.HeapValidate(win32memory.GetProcessHeap(), 0, None)
stdio.printf("[BISM] HV after strcpy(mod_list)=%d\n", hv5)
stdio.fflush(0)
stdlib.free(mod_name) stdlib.free(mod_name)
stdio.printf("[BISM] free(mod_name) OK\n")
stdio.fflush(0)
count += 1 count += 1
stdio.printf("[BISM] before free(sha1=%p)\n", sha1)
stdio.fflush(0)
stdlib.free(sha1) stdlib.free(sha1)
stdio.printf("[BISM] free(sha1) OK\n")
stdio.fflush(0)
stdlib.free(map_buf) stdlib.free(map_buf)
return count return count

View File

@@ -249,7 +249,11 @@ def main() -> int:
ph1_temp: str = Config.TempDir ph1_temp: str = Config.TempDir
if ph1_temp is None: if ph1_temp is None:
ph1_temp = "." ph1_temp = "."
stdio.printf("[DBG MAIN] before Phase1: Inc=%s temp=%s\n", Config.IncludesDir, ph1_temp)
stdio.fflush(0)
Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log) Phase1.RunPhase1(mb, Config.IncludesDir, ph1_temp, log)
stdio.printf("[DBG MAIN] after Phase1\n")
stdio.fflush(0)
# 如果仅 Phase1不执行 Phase2直接退出 # 如果仅 Phase1不执行 Phase2直接退出
if do_phase2 == 0: if do_phase2 == 0:
stdio.printf("[phase] Phase1 完成,退出\n") stdio.printf("[phase] Phase1 完成,退出\n")

1169
Test/crash_log.txt Normal file

File diff suppressed because it is too large Load Diff

1636
Test/crash_log2.txt Normal file

File diff suppressed because it is too large Load Diff

1
Test/crash_out.txt Normal file
View File

@@ -0,0 +1 @@
DBG MemBuddy.alloc: block=0000019B93BE4828

1
Test/crash_out2.txt Normal file
View File

@@ -0,0 +1 @@
DBG MemBuddy.alloc: block=000002428000F828

1
Test/crash_output.txt Normal file
View File

@@ -0,0 +1 @@
[DBG]