摘要

读取战斗日志(Logs,按时间列出“谁对谁做了什么”的面板)时,OCR 会对同一行读多次,程序再决定是输出这行文字,还是保持“未知”。有一些私有的实验规则会把原本“未知”的行升级成输出文字。为了防止这类升级引入错误,之前已经写过一个“保存结果完整性检查器”(v2):拿基线结果和候选结果对比,检查没有偷偷改原框、没有丢原始读数等。

本实验发现 v2 有一个软件漏洞:如果原始读数里藏着一些不常见的换行或分隔控制字符(垂直制表、换页、Unicode 行/段分隔符等),文字规范化和去首尾空白会把它们“抹掉”,于是一个其实跨了两行、或者名字中间被切断的读数也能被接受。另外,v2 判断升级资格时还在用“删掉所有空白再比较”的旧规则,可能让删空格掩盖名字或数字的变化。

v3 在不改动 v2 冻结代码的前提下叠加两道检查。64 个合成用例里,旧版误收的 42 个无效用例 v3 全部拒绝;对 6 份已保存的真实结果做一次检查,全部仍然有效。这是软件完整性检查,不是 OCR 准确率。

要回答的问题

  1. 能否堵上“控制字符被规范化隐藏”和“删空格掩盖语义变化”两个漏洞,同时保留 v2 的所有拒绝?
  2. 已有的真实保存结果在更严格的检查下是否仍然有效?

数据与来源

  • 合成用例 64 个:16 个合法对照、48 个必须拒绝的要求。其中包括 10 种行边界字符在开头/结尾/名字内部三种位置、4 个合法的规范化/空格对照、2 个“未知行带边界字符”的对照,以及之前 28 个语义空格用例。之前的 56 条兼容性要求作为回归用例保留。
  • 6 对已有的真实保存结果(基线 JSON + 候选 JSON),来自之前的日志实验,都是已曝光的开发来源。
  • 不读取图片、不解码视频、不跑 OCR、不读评分参考。

方法

v3 = v2 + 两道附加检查,只返回“有效/无效”和原因,绝不生成替换文字或新结论:

  1. 原始读数边界检查:对每一条将要输出文字的日志行,只要它的任何一次原始读数含有 CR、LF、VT、FF、FS、GS、RS、NEL、LS、PS 这些行/分隔字符,就拒绝——在把规范化后的文字当作证据之前就检查。不删分隔符、不修复。仍保持“未知”的行不做这项检查:坏读数可以作为可见证据留着,只要不输出文字。回合标题沿用 v2 规则。
  2. 语义空格检查:对每个 v2 认为有效的私有升级,再套用之前冻结的语义空格规则:名字、玩家名、法术名、数字和语法词必须原样连续,不允许用删空格来掩盖玩家/单位/标签或数字的变化。

设计和用例都在一次正式检查之前冻结。

设置

在一个新的输出目录保存一次检查结果;分别报告基线输出行、升级行和未变行,以及附加检查的调用次数和耗时(耗时不是 CPU 成本或图片延迟)。

结果

合成用例

项 数
用例总数 64
合法对照 16
必须拒绝 48
与预期不符 0
旧版误收的无效用例 42
新版误收的无效用例 0
新拒绝:边界字符 24
新拒绝:语义空格 18

24 个新拒绝的边界用例就是 VT、FF、FS、GS、RS、NEL、LS、PS 各在开头/结尾/内部三种位置(CR 和 LF 旧版本来就拒绝)。18 个语义用例包括主体/玩家/法术/行动者/目标/能力/效果名中空格被删或插入、伤害/死亡数/括号/持续时间/时钟/谓词被拆开、括号内加空格、跨行合并等。

6 份已保存结果

结果 行 基线输出行 候选输出行 验证的升级 未变
短页(5 行) 6 2 5 3 3
战场负例 0 0 0 0 0
滚动页(29 行) 29 17 27 10 19
洞穴页 7 5 5 0 7
英雄面板负例 0 0 0 0 0
说明框负例 0 0 0 0 0

6 份全部仍然有效。合计:基线输出 24 行、验证升级 13 行、候选输出 37 行、未变 29 行;42 个原生框、126 次原始读数全部保留;37 条输出行做了边界检查,13 个升级做了语义检查。合成检查约 0.019 秒,保存结果检查约 0.005 秒。

新增软件测试 125 项、相关回归 433 项,共 558 项通过。

作为背景,之前的报告(本实验没有重读或重算)记录这批日志可读完整行 36/39 正确、可核验的输出 36/36 正确。

失败与负结果

v2 的漏洞本身就是负结果:42 个本应拒绝的合成用例被旧版接受。本实验没有发现新的真实读数因 v3 被拒——但这只说明这 6 份已保存结果里没有这类问题。

局限

  • 这些是软件验证要求,不是测量到的 OCR 失败。
  • 同一个 OCR 引擎多次读出相同的错字,可以通过所有完整性检查。
  • 6 份结果来自已曝光的开发来源,不是盲测。
  • 没有记录独立的主线验收;没有生产改动。

结论与下一步

v3 堵上了两个可能让错误读数“看起来干净”的漏洞,并保留了 v2 的全部拒绝和所有原始证据。它只能保证“输出没有作弊”,不能保证“读对了”;真正的读取质量仍需在新图片上独立验收。