Files
Viper_VRTE/_withcontent.vp
T
TermiNexus db3be6968f fix(memhub,gzip): 内存池 OOM 归属画像与 free 拒绝现场;gzip 注解 *= 词法粘连
memhub: alloc 失败打印归属 site/ctx 与存活块 order 分布(新增 dump_alive_orders);free 被 _is_valid_ptr 拒绝时首次打印现场;接通 big_alloc_count

gzip: ub: uchar*= buf 补空格(*= 被词法合并为单 OP,注解止于 uchar)

新增 traceback 模块;删除 dbgstack.vp;其余模块随新语法与尺寸口径同步
2026-09-26 19:27:24 +08:00

80 lines
3.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
from stdint import *
from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue
import stdlib
import stdio
import string
# Maximum provider stack depth (compiler verifies sufficiency; increase if needed)
define _MAX_PROVIDER_DEPTH = 32
class _ProviderStack:
"""Provider stack, stores pairs of field names and pointers."""
# Field names are stored as string pointers: a `char` element would hold a
# single byte, truncating the name and breaking every provider lookup.
names: [32]str
ptrs: [32]rawptr
top: uint64
# TLS index (global; all threads share the same index)
_tls_index: ulong = 0
@t.TLS
def _init_tls():
"""Initialize TLS index (executes once; subsequent calls are skipped)."""
global _tls_index
# 双保险:TPV 已正式实现 @t.TLS(函数级一次性守卫,首次执行后置
# __tls_init_done 标志,后续调用直接返回),此判重守卫保留以兼容
# 尚未重建的旧 TPV.exe。_tls_index 初始为 0(TlsAlloc 成功不会返回 0)。
if _tls_index == 0:
_tls_index = TlsAlloc()
def _get_stack() -> _ProviderStack*:
"""Obtain current thread's provider stack. Allocate one if none exists."""
_init_tls()
stack: _ProviderStack* = TlsGetValue(_tls_index)
if stack == None:
stack = stdlib.malloc(_ProviderStack.__sizeof__())
string.memset(stack, 0, _ProviderStack.__sizeof__())
TlsSetValue(_tls_index, stack)
return stack
def _push_provider(field_name: str, ptr: rawptr):
"""Push a provider (field_name, ptr) onto the stack."""
stack: _ProviderStack* = _get_stack()
if stack.top >= _MAX_PROVIDER_DEPTH:
stdio.printf("[with] ERROR: provider stack overflow (depth=%lu, max=%d), field '%s' not injected\n", stack.top, _MAX_PROVIDER_DEPTH, field_name)
return
stack.names[stack.top] = field_name
stack.ptrs[stack.top] = ptr
stack.top = stack.top + 1
def _pop_provider():
"""Pop the top provider entry from the stack."""
stack: _ProviderStack* = _get_stack()
if stack.top > 0:
stack.top = stack.top - 1
def _find_provider(field_name: str) -> rawptr:
"""Search for matching field_name starting from stack top.
Return associated pointer, or NULL if no match found."""
stack: _ProviderStack* = _get_stack()
# 上界显式转 t.CInt(有符号):本循环是「递减 + stop 为 -1」形态,若上界
# 被当作无符号(stack.top 是 uint64 字段),比较谓词会退化为 ugt,而 -1 在
# 无符号域是 UINT32_MAX ⇒ 条件恒假、循环体不可达、本函数恒返回 NULL(with 的
# __mbuddy__ 注入全部失效,_str.upper 对 NULL 取 vtable 崩溃)。显式转换让
# 符号域与递减语义一致,与编译器侧「stop 为负字面量时退回有符号谓词」互为双保险。
for i in range(int(stack.top) - 1, -1, -1):
# Content comparison: every string literal gets its own constant, so the
# push/find pointers differ and pointer equality never matches.
if string.strcmp(stack.names[i], field_name) == 0: return stack.ptrs[i]
return None