diff --git a/viperlib.vp b/viperlib.vp index 4a8d1e3..36b7a9c 100644 --- a/viperlib.vp +++ b/viperlib.vp @@ -28,17 +28,23 @@ export def snprintf(buf: str, size: sizet, fmt: str, *args) -> int: ret: int = vsnprintf(buf, size, fmt, args) return ret -# Check floating-point special values (IEEE 754) -# Return: 0=normal, 1=+inf, 2=-inf, 3=nan +# 检查浮点特殊值(IEEE 754) +# 返回:0=正常, 1=+inf, 2=-inf, 3=nan +# 注意:不可用位双关 `*&fbits = *&fv` 读取 IEEE 位模式——该赋值会被编译器静默 +# 丢弃(IR 中 fbits 恒为 0,见 TransPyV/output/db514c1af999c5f5.text.ll),会使 +# 本函数恒返回 0、特殊值检查彻底失效,进而让 inf 进入浮点格式化循环而死循环。 +# 这里改用纯浮点语义判定,不依赖任何位操作: +# NaN :fv != fv 为真 +# ±inf:fv - fv 得到 NaN(有限值得到 0.0) def _check_special_float(fv: double) -> int: - fbits: uint64 = 0 - *&fbits = *&fv - if ((fbits >> 52) & 0x7FF) != 0x7FF: return 0 - is_neg: int = 1 if (fbits >> 63) != 0 else 0 - if (fbits & 0x000FFFFFFFFFFFFF) == 0: - if is_neg: return 2 + if fv != fv: + return 3 + diff: double = fv - fv + if diff != diff: + if fv < 0.0: + return 2 return 1 - return 3 + return 0 export def vsnprintf(buf: bytes, size: sizet, fmt: str, ap: str) -> int: if fmt is None: return 0 @@ -626,8 +632,11 @@ export def vsnprintf(buf: bytes, size: sizet, fmt: str, ap: str) -> int: di = 1 else: scale: double = 1.0 - while work >= scale * 10.0: + # 上界防护:inf 会让 `work >= scale*10.0` 永真,正常有限值最多 308 次 + scale_guard: int = 0 + while work >= scale * 10.0 and scale_guard < 400: scale *= 10.0 + scale_guard += 1 while scale >= 1.0 and di < TEMP_BUF_SIZE - 1: d: int = int(work / scale) if d > 9: d = 9 @@ -779,12 +788,17 @@ export def vsnprintf(buf: bytes, size: sizet, fmt: str, ap: str) -> int: ptr += _step exp10: int = 0 if fv != 0.0: - while fv >= 10.0: + # 上界防护:inf 会让下面两个循环永真(inf/10==inf、inf*10==inf) + exp_guard: int = 0 + while fv >= 10.0 and exp_guard < 400: fv /= 10.0 exp10 += 1 - while fv < 1.0: + exp_guard += 1 + exp_guard = 0 + while fv < 1.0 and exp_guard < 400: fv *= 10.0 exp10 -= 1 + exp_guard += 1 int_digit: int = int(fv) if int_digit > 9: int_digit = 9 if int_digit < 0: int_digit = 0 @@ -971,12 +985,17 @@ export def vsnprintf(buf: bytes, size: sizet, fmt: str, ap: str) -> int: fv_orig: double = fv exp10: int = 0 if fv != 0.0: - while fv >= 10.0: + # 上界防护:卡死现场即此循环(inf 会让 fv>=10.0 永真,inf/10==inf) + exp_guard: int = 0 + while fv >= 10.0 and exp_guard < 400: fv /= 10.0 exp10 += 1 - while fv < 1.0: + exp_guard += 1 + exp_guard = 0 + while fv < 1.0 and exp_guard < 400: fv *= 10.0 exp10 -= 1 + exp_guard += 1 g_use_e: int = 0 if exp10 < -4 or exp10 >= precision: g_use_e = 1 @@ -1029,8 +1048,11 @@ export def vsnprintf(buf: bytes, size: sizet, fmt: str, ap: str) -> int: g_len = 1 else: scale: double = 1.0 - while work >= scale * 10.0: + # 上界防护:inf 会让 `work >= scale*10.0` 永真,正常有限值最多 308 次 + scale_guard: int = 0 + while work >= scale * 10.0 and scale_guard < 400: scale *= 10.0 + scale_guard += 1 while scale >= 1.0 and g_len < TEMP_BUF_SIZE - 1: d: int = int(work / scale) if d > 9: d = 9