fix(tpv): 泛型污染检测改 token 边界匹配(根治 strstr 误杀合法特化)
- _list.vp L57 elem_ptr: T | t.CPtr 在 list[AST|t.CPtr] 特化时被误报污染:strstr('e9dfb296a8674aee.AST|t.CPtr', 'T') 把 AST 内部字符 T 当参数名
- 新增 _str_contains_ident:独立标识符检测(两侧非字母/数字/_),实参内部字符不算污染
- T→T 完全自映射仍直接报错(明确污染);子串场景按边界判定
This commit is contained in:
1 parent
27ba74c720
commit
8445af93d2
1 file changed
+43
-1
@@ -310,6 +310,42 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
return res_c
|
||||
# ---- 6. 查不到:保持原样 ----
|
||||
return type_name
|
||||
|
||||
def _str_contains_ident(self, s: str, ident: str) -> int:
|
||||
"""检查 s 中是否包含独立标识符 ident(两侧非字母/数字/下划线)
|
||||
|
||||
用于泛型实参污染检测:单字符参数名(如 'T')在实参串 "AST|t.CPtr"
|
||||
中作为 AST/CPtr 内部字符出现时不算污染——必须两侧是边界
|
||||
(空格/|/[/]/,等)才算独立标识符。strstr 子串匹配会把实参内部
|
||||
的 'T' 误判为参数名 → 合法特化 list[AST|t.CPtr] 被误杀。
|
||||
"""
|
||||
if s is None or ident is None or ident[0] == '\0':
|
||||
return 0
|
||||
s_len: t.CSizeT = string.strlen(s)
|
||||
id_len: t.CSizeT = string.strlen(ident)
|
||||
if id_len == 0 or s_len < id_len:
|
||||
return 0
|
||||
i: t.CSizeT
|
||||
for i in range(s_len - id_len + 1):
|
||||
if string.strncmp(s + i, ident, id_len) != 0:
|
||||
continue
|
||||
# 左边界:i==0 或前一字符非标识符字符
|
||||
left_ok: int = 1
|
||||
if i > 0:
|
||||
lc: t.CChar = s[i - 1]
|
||||
if (lc >= 'a' and lc <= 'z') or (lc >= 'A' and lc <= 'Z') \
|
||||
or (lc >= '0' and lc <= '9') or lc == '_':
|
||||
left_ok = 0
|
||||
right_ok: int = 1
|
||||
if i + id_len < s_len:
|
||||
rc: t.CChar = s[i + id_len]
|
||||
if (rc >= 'a' and rc <= 'z') or (rc >= 'A' and rc <= 'Z') \
|
||||
or (rc >= '0' and rc <= '9') or rc == '_':
|
||||
right_ok = 0
|
||||
if left_ok != 0 and right_ok != 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _parse_type_string(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
type_str: str,
|
||||
ctx: t.CInt) -> ast.AST | t.CPtr:
|
||||
@@ -1265,7 +1301,13 @@ class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
gp_j: t.CSizeT
|
||||
for gp_j in range(gp_n):
|
||||
gp_pn: str = tpn_g.get(gp_j)
|
||||
if gp_pn is not None and string.strstr(gp_ta, gp_pn) is not None:
|
||||
# token 边界匹配(非 strstr 子串):实参串中必须出现
|
||||
# "独立标识符"参数名(两侧非字母/数字/_)。否则 strstr
|
||||
# 把实参内部字符误判为参数名——"e9dfb296a8674aee.AST|
|
||||
# t.CPtr" 含 'T' 字符但 T 在 AST/CPtr 内部不是独立
|
||||
# 参数名 → 合法特化 list[AST|t.CPtr] 被误杀(_list.vp
|
||||
# L57 elem_ptr: T | t.CPtr 根因)。
|
||||
if gp_pn is not None and self._str_contains_ident(gp_ta, gp_pn) != 0:
|
||||
polluted = 1
|
||||
break
|
||||
if polluted != 0:
|
||||
|
||||
Reference in new issue
Block a user