fix(gen): 消除 ViperC 侧 P0 级静默截断
match:case 数超过 MAX_MATCH_CASES 时 fail-fast(原先 break 会静默少分支,need_case 检查也发现不了)。vtable:初始化串按真实方法表动态分配,_vtable_strcat 溢出改 fatal;VTBL_METHOD_MAX 超限不再 break(原先子类 override 静默失效)。符号名:coro_pool_/__tls_init_done_/__decor_rec_/闭包 fn_ptr 的定义与引用改为按实际长度分配,消除 96 vs 128、64 vs 128 的不对称。Stub:_PyiEmit 溢出改 VLogger.error(半截 .vpi 会被当完整文件解析);VpiReader 参数段/返回注解缓存槽放不下时 fail-fast,不再丢段导致形参注解错位。Includes:文件超过 1MiB 拒绝哈希(SHA1 冲突会让两个模块共用缓存);add_file_entry 失败不再被忽略。f-string:格式串按字面量/转换符实际长度分配,字面量与 format_spec 溢出 fail-fast。
This commit is contained in:
1 parent
15952d3852
commit
3e1e1fc1b3
10 files changed
+183
-72
No files matched your search
@@ -144,15 +144,20 @@ def _pyi_cdefine_found() -> int:
|
||||
|
||||
|
||||
# ============================================================
|
||||
# _PyiEmit - append text to buf at pos, returning the new pos (truncates on overflow)
|
||||
# _PyiEmit - append text to buf at pos, returning the new pos (overflow is fatal)
|
||||
def _PyiEmit(buf: bytes, buf_size: sizet, pos: sizet, text: str) -> sizet:
|
||||
"""Append text to buf at pos and return the new pos"""
|
||||
if buf is None or text is None or pos >= buf_size: return pos
|
||||
"""Append text to buf at pos and return the new pos.
|
||||
|
||||
Overflow used to truncate silently, and the truncated .vpi was then parsed as if complete:
|
||||
the consuming module silently lost declarations or got half a signature.
|
||||
"""
|
||||
if buf is None or text is None: return pos
|
||||
tlen: sizet = string.strlen(text)
|
||||
if tlen == 0: return pos
|
||||
remain: sizet = buf_size - pos
|
||||
if tlen >= remain: tlen = remain - 1
|
||||
if tlen > 0: string.memcpy(buf + pos, text, tlen)
|
||||
if pos + tlen + 1 > buf_size:
|
||||
VLogger.error(f"generated .vpi stub text exceeds the {buf_size}-byte buffer; raise PYI_BUF_SIZE", "StubGen")
|
||||
return pos
|
||||
string.memcpy(buf + pos, text, tlen)
|
||||
return pos + tlen
|
||||
|
||||
|
||||
|
||||
@@ -400,6 +400,11 @@ def _cache_vpi_return_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
cls_len2: sizet = 0
|
||||
if cur_cls is not None: cls_len2 = string.strlen(cur_cls)
|
||||
key_len: sizet = sha1_len + 1 + cls_len2 + 1 + mname_len
|
||||
# fail-fast: cache entries are fixed-size slots. Skipping a too-long key or
|
||||
# return text leaves the method without a cached return type, and callers
|
||||
# then fall back to i32 (pointer returns get truncated).
|
||||
if key_len >= VPI_KEY_LEN or rtype_len >= VPI_RET_LEN:
|
||||
VLogger.error(f"return-annotation cache slot too small (key {key_len}/{VPI_KEY_LEN} bytes, return {rtype_len}/{VPI_RET_LEN} bytes); shorten the class/method name or the return annotation", "VpiReader")
|
||||
if key_len < VPI_KEY_LEN and rtype_len < VPI_RET_LEN:
|
||||
# copy method name to a temp buffer (vpi_buf+dstart is not NUL-terminated)
|
||||
mname_buf: bytes = stdlib.malloc(mname_len + 1)
|
||||
@@ -575,6 +580,10 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
while a_start < s_end and vpi_buf[a_start] == ' ': a_start += 1
|
||||
a_end: sizet = s_end
|
||||
while a_end > a_start and vpi_buf[a_end - 1] == ' ': a_end -= 1
|
||||
# fail-fast: dropping a segment shifts every later parameter's annotation onto
|
||||
# the wrong parameter (declare/define type mismatch), which is worse than a miss.
|
||||
if plist_pos + (a_end - a_start) + 1 >= VPI_PARAM_LEN:
|
||||
VLogger.error(f"parameter annotation list exceeds the {VPI_PARAM_LEN}-byte cache slot; shorten this method's annotations", "VpiReader")
|
||||
if plist_pos + (a_end - a_start) + 1 < VPI_PARAM_LEN:
|
||||
if seg_written > 0:
|
||||
plist[plist_pos] = '@'
|
||||
@@ -592,6 +601,10 @@ def _cache_vpi_param_annots_text(vpi_buf: bytes, src_sha1: str) -> int:
|
||||
cls_len2: sizet = 0
|
||||
if cur_cls is not None: cls_len2 = string.strlen(cur_cls)
|
||||
key_len: sizet = sha1_len + 1 + cls_len2 + 1 + mname_len
|
||||
if key_len >= VPI_PARAM_KEY_LEN:
|
||||
# fail-fast: a skipped key silently loses the whole parameter annotation
|
||||
# list (the caller then rebuilds declare params from the degraded text).
|
||||
VLogger.error(f"parameter-annotation cache key exceeds {VPI_PARAM_KEY_LEN} bytes (class/method name too long)", "VpiReader")
|
||||
if key_len < VPI_PARAM_KEY_LEN:
|
||||
mname_buf: bytes = stdlib.malloc(mname_len + 1)
|
||||
if mname_buf is not None:
|
||||
|
||||
Reference in new issue
Block a user