feat(types): 禁止隐式窄化(整数 高→低);_tb_read_whole 容量改 sizet

规则收紧(2026-10-10):整数位宽 高→低 隐式窄化一律 fail-fast(CastError),仅两类豁免:① 目标 i1 的真值归一化;② 源是编译期常量且值落进目标位宽。_scalar_convert_reason 的 int↔int 同步改为'目标位宽≥源位宽才 PC_OK'。BuildPipeline._tb_read_whole 去掉 ULONG(sz)+ULONG(2) 的窄化,改 sizet(sz)+2。
This commit is contained in:
TermiNexus committed 2026-10-10 21:57:18 +08:00
1 parent 9db3748f68
commit 5bb6538703
2 files changed
+43 -35

No files matched your search

+26 -25
View File
@@ -7,11 +7,11 @@ import stdlib
import memhub
import viperlib
import vthreading
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import w32.win32process as win32process
import w32.win32sync as win32sync
import win32.fileio as fileio
import win32.win32file
import win32.win32base
import win32.win32process as win32process
import win32.win32sync as win32sync
import subprocess
import viperlib
import ast
@@ -280,8 +280,8 @@ def ensure_dir(path: str) -> int:
# Hot path (PROF: ensure_dir was 4.5%): if the final dir exists, return success early,
# saving an alloc + N+1 CreateDirectoryA calls. Semantics unchanged (exists == success).
attr: ULONG = w32.win32file.GetFileAttributesA(path)
if attr != 0xFFFFFFFF and (attr & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: return 0
attr: ULONG = win32.win32file.GetFileAttributesA(path)
if attr != 0xFFFFFFFF and (attr & win32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: return 0
# copy the path into a writable buffer (for stepwise truncation)
buf: bytes = _mbuddy.alloc(path_len + 1)
@@ -296,11 +296,11 @@ def ensure_dir(path: str) -> int:
if ch == 47 or ch == 92: # '/' = 47, '\\' = 92
saved: int = ch
buf[i] = '\0'
w32.win32file.CreateDirectoryA(buf, None)
win32.win32file.CreateDirectoryA(buf, None)
buf[i] = saved
# create the final directory
w32.win32file.CreateDirectoryA(buf, None)
win32.win32file.CreateDirectoryA(buf, None)
return 0
@@ -567,15 +567,15 @@ def _run_cmd_wait(cmd: str) -> int:
cmd_line: bytes = stdlib.malloc(cl_len + 1)
if cmd_line is None: return -1
string.strcpy(cmd_line, cmd)
sa: w32.win32base.SECURITY_ATTRIBUTES = w32.win32base.SECURITY_ATTRIBUTES()
sa: win32.win32base.SECURITY_ATTRIBUTES = win32.win32base.SECURITY_ATTRIBUTES()
si: win32process.STARTUPINFOA = win32process.STARTUPINFOA()
pi: win32process.PROCESS_INFORMATION = win32process.PROCESS_INFORMATION()
# T() only allocas, no memset: unset STARTUPINFOA fields are stack garbage, so concurrent
# threads get random dwFlags and CreateProcessA uses junk stdio handles. Clear si/sa/pi.
string.memset(&si, 0, win32process.STARTUPINFOA.__sizeof__())
string.memset(&sa, 0, w32.win32base.SECURITY_ATTRIBUTES.__sizeof__())
string.memset(&sa, 0, win32.win32base.SECURITY_ATTRIBUTES.__sizeof__())
string.memset(&pi, 0, win32process.PROCESS_INFORMATION.__sizeof__())
sa.nLength = w32.win32base.SECURITY_ATTRIBUTES.__sizeof__()
sa.nLength = win32.win32base.SECURITY_ATTRIBUTES.__sizeof__()
sa.lpSecurityDescriptor = t.CPtr(0)
sa.bInheritHandle = 1
si.cb = win32process.STARTUPINFOA.__sizeof__()
@@ -585,15 +585,15 @@ def _run_cmd_wait(cmd: str) -> int:
# CreateProcessA failure diagnostics: read GetLastError immediately (later calls overwrite
# it). Use warning, not error (error would sys.exit in a worker thread).
if ok == 0:
cp_err: uint32 = w32.win32base.GetLastError()
cp_err: uint32 = win32.win32base.GetLastError()
VLogger.warning(f"CreateProcessA failed (GetLastError={cp_err}) external command not started: cmd={cmd}", "LLC")
stdlib.free(cmd_line)
if ok == 0: return -1
win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE)
win32sync.WaitForSingleObject(pi.hProcess, win32.win32base.INFINITE)
exit_code: uint32 = 0
win32process.GetExitCodeProcess(pi.hProcess, &exit_code)
w32.win32base.CloseHandle(pi.hProcess)
w32.win32base.CloseHandle(pi.hThread)
win32.win32base.CloseHandle(pi.hProcess)
win32.win32base.CloseHandle(pi.hThread)
return int(exit_code)
@@ -673,7 +673,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
h_j: t.CPtr = t.CPtr(handles.get(batch_start + j))
wr: uint32 = win32sync.WaitForSingleObject(h_j, 600000)
if wr != 0: VLogger.error("llc thread join timeout/failure (not finished within 600 seconds)", "PhaseB")
w32.win32base.CloseHandle(h_j)
win32.win32base.CloseHandle(h_j)
# check this batch's results
for j in range(batch_n):
tsk2: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size)
@@ -702,11 +702,11 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, out_buf: bytes, out_pos: sizet, out_size: sizet) -> sizet:
"""Recursively scan base_dir, collect .obj paths into out_buf, return the new out_pos."""
find_data: w32.win32file.WIN32_FIND_DATAA* = _mbuddy.alloc(w32.win32file.WIN32_FIND_DATAA.__sizeof__())
find_data: win32.win32file.WIN32_FIND_DATAA* = _mbuddy.alloc(win32.win32file.WIN32_FIND_DATAA.__sizeof__())
if find_data is None:
VLogger.warning("_CollectObjFilesImpl failed to allocate find_data, fewer .obj collected", "collect")
return out_pos
string.memset(find_data, 0, w32.win32file.WIN32_FIND_DATAA.__sizeof__())
string.memset(find_data, 0, win32.win32file.WIN32_FIND_DATAA.__sizeof__())
pattern: bytes = _mbuddy.alloc(bd_len + 8)
if pattern is None:
@@ -714,9 +714,9 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, out_buf: bytes, out_pos:
return out_pos
viperlib.snprintf(pattern, bd_len + 8, "%s/*", base_dir)
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, find_data)
handle: win32.win32base.HANDLE = win32.win32file.FindFirstFileA(pattern, find_data)
_mbuddy.free(pattern)
if handle == w32.win32base.INVALID_HANDLE_VALUE:
if handle == win32.win32base.INVALID_HANDLE_VALUE:
VLogger.warning("_CollectObjFilesImpl cannot open directory, fewer .obj collected", "collect")
return out_pos
@@ -732,7 +732,7 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, out_buf: bytes, out_pos:
if is_dot == 0:
attrs: ULONG = find_data.dwFileAttributes
is_dir: int = 0
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: is_dir = 1
if (attrs & win32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0: is_dir = 1
if is_dir != 0:
# recurse into the subdirectory
sub_dir: bytes = _mbuddy.alloc(bd_len + fname_len + 2)
@@ -752,9 +752,9 @@ def _CollectObjFilesImpl(base_dir: str, bd_len: sizet, out_buf: bytes, out_pos:
viperlib.snprintf(out_buf + out_pos, need, "%s/%s", base_dir, fname)
out_pos += bd_len + 1 + fname_len
if w32.win32file.FindNextFileA(handle, find_data) == 0: break
if win32.win32file.FindNextFileA(handle, find_data) == 0: break
w32.win32file.FindClose(handle)
win32.win32file.FindClose(handle)
return out_pos
@@ -1823,7 +1823,8 @@ def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str:
if buf is None:
f.close()
return None
got: LONG = f.read_all(buf, ULONG(sz) + ULONG(2))
# 容量全程用 sizet(与 sz 同宽):旧写法 ULONG(sz) + ULONG(2) 会在 sz >= 4GiB 时静默回绕
got: LONG = f.read_all(buf, sizet(sz) + 2)
f.close()
if got < 0: return None
return buf