修正了 TPC 的一些错误,包括 Test 维护后 TPV 无法重新编译或重编译后越界的部分问题

This commit is contained in:
2026-07-20 11:12:30 +08:00
parent ab73420b4f
commit a277ded8d4
476 changed files with 4000 additions and 3439 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)
f.close()
if bytes_read <= 0:
stdlib.free(buf)
return None
# 原地去除 \rCRLF → LF与 Projectrans.py 文本模式读取一致
@@ -189,17 +190,21 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
# 计算 SHA1
ctx: hashlib.sha1 | t.CPtr = hashlib.sha1()
if ctx is None:
stdlib.free(buf)
return None
ctx.update(buf)
digest: bytes = stdlib.malloc(hashlib.SHA1_DIGEST_LEN)
if digest is None:
stdlib.free(buf)
return None
ctx.final(digest)
# 转为十六进制字符串(取前 8 字节 = 16 个十六进制字符)
hex_buf: str = stdlib.malloc(17)
if hex_buf is None:
stdlib.free(buf)
stdlib.free(digest)
return None
for i in range(8):
hi: int = (digest[i] >> 4) & 0xF
@@ -213,6 +218,9 @@ def compute_file_sha1(pool: memhub.MemBuddy | t.CPtr,
else:
hex_buf[i * 2 + 1] = 'a' + (lo - 10)
hex_buf[16] = '\0'
# 释放临时缓冲区hex_buf 由调用者负责释放)
stdlib.free(buf)
stdlib.free(digest)
return hex_buf
@@ -245,6 +253,8 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
handle: win32base.HANDLE = win32file.FindFirstFileA(pattern, find_data)
if handle == win32base.INVALID_HANDLE_VALUE:
stdlib.free(pattern)
stdlib.free(find_data)
return 1
# 遍历所有文件和子目录
@@ -284,6 +294,7 @@ def scan_directory_recursive(pool: memhub.MemBuddy | t.CPtr,
prefix_len = string.strlen(rel_prefix)
rel_path: bytes = stdlib.malloc(prefix_len + fname_len + 2)
if rel_path is None:
stdlib.free(full_path)
break
if rel_prefix is not None and prefix_len > 0:
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)
if sha1 is not None:
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
win32file.FindClose(handle)
stdlib.free(pattern)
stdlib.free(find_data)
return 0
@@ -341,7 +360,8 @@ def scan_includes(pool: memhub.MemBuddy | t.CPtr,
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

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,
log: VLogger.Logger | t.CPtr) -> int:
"""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:
stdio.printf("[Phase1] includes_dir 或 temp_dir 为空,跳过\n")
return 1
stdio.printf("[P1] before log.banner\n")
stdio.fflush(0)
if log is not None:
log.banner("Phase1: 扫描 includes按需翻译")
stdio.printf("[P1] after log.banner\n")
stdio.fflush(0)
# 扫描 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)
stdio.printf("[P1] after scan_includes: result=%p\n", result)
stdio.fflush(0)
if result is None:
stdio.printf("[Phase1] 扫描失败\n")
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 集合
# 优先使用 Projectrans.py 生成的 _sha1_map.txt含依赖分析只包含需要的 includes
# 若不存在,则从扫描结果生成(包含所有 includes可能导致结构体表溢出
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:
stdio.printf("[Phase1] sha1_set 分配失败\n")
return 1
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)
stdio.printf("[P1] set_count=%d\n", set_count)
stdio.fflush(0)
if set_count <= 0:
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)
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)
stdio.printf("[P1] set_count2=%d\n", set_count)
stdio.fflush(0)
if set_count < 0:
stdio.printf("[Phase1] 无法加载 _sha1_map.txt跳过 Phase1\n")
return 1
stdio.printf("[Phase1] includes SHA1 集合: %d\n", set_count)
stdio.fflush(0)
# 构建模块 SHA1 映射(供跨模块函数调用名混淆使用)
td_len_p1map: t.CSizeT = string.strlen(temp_dir)
p1_sha1_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 17)
p1_mod_arr: bytes = stdlib.malloc(StubMerger.MAX_INCLUDES * 64)
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:
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)
stdio.printf("[P1] after set_module_sha1_map\n")
stdio.fflush(0)
# 初始化 AST 表(只需一次)
ast._init_tables(mb)

View File

@@ -8,6 +8,7 @@ import llvmlite
import w32.win32file as win32file
import w32.win32base as win32base
import w32.fileio as fileio
import w32.win32memory as win32memory
import viperlib
import sys
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)
if f.closed:
stdio.printf("[StubMerger] _sha1_map.txt 不存在: %s\n", map_path)
stdlib.free(map_path)
return -1
# 读取内容(使用 stdlib.malloc 避免 mbuddy 池耗尽)
@@ -76,10 +78,13 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
content: str = stdlib.malloc(MAP_BUF_SIZE)
if content is None:
f.close()
stdlib.free(map_path)
return -1
bytes_read: t.CInt64T = f.read_all(content, MAP_BUF_SIZE)
f.close()
stdlib.free(map_path)
if bytes_read <= 0:
stdlib.free(content)
return -1
content[bytes_read] = '\0'
@@ -112,6 +117,7 @@ def _load_includes_sha1_set(pool: memhub.MemBuddy | t.CPtr,
sha1_set[count * 17 + 16] = '\0'
count += 1
stdlib.free(content)
return count
@@ -189,6 +195,8 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy | t.CPtr, temp_dir: str,
written_count += 1
f.close()
stdlib.free(map_path)
stdlib.free(line_buf)
stdio.printf("[Phase1] 已写入 _sha1_map.txt (%d 个 includes)\n", written_count)
return 0
@@ -735,14 +743,32 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
map_buf[map_br] = '\0'
else:
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
pos: t.CSizeT = 0
while pos < map_br and count < MAX_INCLUDES:
stdio.printf("[BISM] iter=%d pos=%d\n", count, pos)
stdio.fflush(0)
# 提取 SHA116 hex
sha1: t.CChar | t.CPtr = stdlib.malloc(17)
stdio.printf("[BISM] malloc(17)=%p\n", sha1)
stdio.fflush(0)
if sha1 is None:
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)
sha1[16] = '\0'
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':
pos += 1
path_len: t.CSizeT = pos - path_start
stdio.printf("[BISM] path_len=%d\n", path_len)
stdio.fflush(0)
# 跳过 \r\n 或 \n
if pos < map_br and map_buf[pos] == '\r':
pos += 1
@@ -765,25 +793,49 @@ def _BuildIncludesSha1Map(temp_dir: str, td_len: t.CSizeT,
# 否则用户文件会被误判为 includes导致 is_module_imported 模块名不匹配而跳过加载
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)
stdio.printf("[BISM] malloc(%d)=%p\n", path_len + 1, path_buf)
stdio.fflush(0)
if path_buf is not None:
string.strncpy(path_buf, map_buf + path_start, path_len)
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)
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)
if mod_name is not None:
# 存储 sha1 和 mod_name 到数组中
idx: t.CSizeT = t.CSizeT(count) * 17
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
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:
string.strcpy(mod_list + idx2, mod_name)
else:
string.strncpy(mod_list + idx2, mod_name, 63)
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)
stdio.printf("[BISM] free(mod_name) OK\n")
stdio.fflush(0)
count += 1
stdio.printf("[BISM] before free(sha1=%p)\n", sha1)
stdio.fflush(0)
stdlib.free(sha1)
stdio.printf("[BISM] free(sha1) OK\n")
stdio.fflush(0)
stdlib.free(map_buf)
return count