图库: 修 M27 评审 P1 门控旁路 + 三个 P2(r1)

P1-1:判定为 backend 的页不再无条件放行 + 后端中途失败不再静默回退 stb。
- meow_img_load_file_step_ex 增加 allow_stb_fallback 参数:0 = 只试后端,
  失败返回 NULL(坏图占位),绝不回落 stb。阅读器按 dec.path 传入。
- 旧行为实测:截断 12MP JPEG 18,403kB、3000×3000 24bpp 头-only BMP 36,056kB、
  非法位深 PNG 16,409kB(stb 都"成功"出图)。修复后:
  截断 JPEG 275kB→NULL、头-only BMP 908kB→NULL、非法位深 PNG 门控占位(0 分配)。

P2-1:PNG 支持矩阵补 png_depth_ok 同式(color 2/4/6 仅 8/16;color 3 无 16;
color 0 允许 1/2/4/8/16),不再出现「矩阵说支持、后端拒绝」。
P2-2:后端命中页也保留两道安全阀:MemAvailable<6MB 占位、估算 >12MB 硬上限占位。
P2-3:B8 指标改为「窗口稳定后只 reset 一次」,量整个 30 翻窗口内相对稳态基线的
最大存活增量(淘汰不再掩盖峰值),并打印稳态/驻留/增量。
P2-4:page_source.h 的估算精度口径限定为「后端命中/典型页」。

回归:
- B7c 新增截断 12MP JPEG / 24bpp 头-only BMP / 非法位深 PNG,断言 backend-only
  NULL 且峰值 ≤3MB、或 stb 门控占位;B7 典型页与 B7b 回退矩阵保持全绿。
- test_reader_many_pages 恢复 24bpp 头-only 夹具(1bpp 保留):24bpp 判 failed、
  1bpp 判 skipped;断言 failed=2 / skipped=1。
- run_tests.sh / run_webtoon_tests.sh EXIT=0;sdk/test_meow_img_stream ALL PASS;
  交叉构建(SDK + tuku)零警告。
This commit is contained in:
AskaEth committed 2026-11-06 11:46:16 +08:00
1 parent 1725af631b
commit 11e09af7a4
8 files changed
+171 -49

No files matched your search

+34
View File
@@ -93,6 +93,40 @@ def main():
big.convert("CMYK").save(os.path.join(out, "cmyk.jpg"), "JPEG", quality=60)
write_adam7(os.path.join(out, "adam7.png"), pattern(1600, 2400))
pattern(1600, 2400).convert("1").save(os.path.join(out, "mono1.bmp"), "BMP")
# ---- M27 r1(P1-1):头部判支持但解码中途失败/后端拒绝的坏文件 ----
# 1) 截断的 12MP JPEG:SOF 仍在(probe/矩阵判 backend),熵段被腰斩 → 后端失败;
# 旧实现会静默回退 stb 并分配 ~18MB。
with open(os.path.join(out, "mp12.jpg"), "rb") as f:
blob = f.read(200000)
with open(os.path.join(out, "trunc2000.jpg"), "wb") as f:
f.write(blob)
# 2) 3000x3000 24bpp BMP,只有 54 字节头(无像素):矩阵判 backend,后端失败;
# 旧实现回退 stb 会 malloc 36MB 并"解出"一张全黑图。
hdr = bytearray(54)
hdr[0:2] = b"BM"
struct.pack_into("<I", hdr, 2, 54) # 谎报文件大小
struct.pack_into("<I", hdr, 10, 54) # 像素数据偏移
struct.pack_into("<I", hdr, 14, 40) # BITMAPINFOHEADER
struct.pack_into("<i", hdr, 18, 3000) # width
struct.pack_into("<i", hdr, 22, 3000) # height
struct.pack_into("<H", hdr, 26, 1) # planes
struct.pack_into("<H", hdr, 28, 24) # bpp
with open(os.path.join(out, "hdr3000.bmp"), "wb") as f:
f.write(hdr)
# 3) 非法位深 PNG(color=2 RGB + depth=1):后端 png_depth_ok 拒绝 → 必须判 stb;
# 旧矩阵只按 color 算位宽 → 误判 backend,失败后回退 stb 分配 ~16MB。
w, h = 1600, 2400
rowbytes = (w * 3 + 7) // 8 # 600 字节/行(depth=1 RGB)
raw = bytearray()
for y in range(h):
raw.append(0)
raw += bytes((x * 7 + y) & 0xFF for x in range(rowbytes))
ihdr = struct.pack(">IIBBBBB", w, h, 1, 2, 0, 0, 0)
data = (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", ihdr) +
chunk(b"IDAT", zlib.compress(bytes(raw))) + chunk(b"IEND", b""))
with open(os.path.join(out, "baddepth.png"), "wb") as f:
f.write(data)
return 0