Skip to content

fix(core): structure_service 业务异常回执 + 写入前可读尺寸校验 - #1150

Closed
STARDUSTLC666 wants to merge 3 commits into
FuRongJun-1999:mainfrom
STARDUSTLC666:fix/1106-structure-bounds-20261030
Closed

STARDUSTLC666 wants to merge 3 commits into
FuRongJun-1999:mainfrom
STARDUSTLC666:fix/1106-structure-bounds-20261030

Conversation

@STARDUSTLC666

Copy link
Copy Markdown
Contributor

修复 #1106(high×2,core/structure_service):

改了什么 / 为什么

  • dispatch 捕获 OverflowError / RecursionError 并转 WriteError(两者都不是 ValueError 子类,旧 handler 的 except (WriteError, ValueError, UnicodeError) 接不住,连接被静默关闭,客户端只收到 EOF)。
  • _receive 捕获深层 JSON 的 RecursionError 与 json.JSONDecodeError;_send 捕获深层响应的 RecursionError,统一返回结构化错误回执。
  • structure_writer 新增 _require_readable:record_event / propose 在事务内按读取视图估算响应尺寸,超过 MAX_RECORD_BYTES(1 MiB − 4 KiB)即 WriteError 并回滚——保证「可写入集合 ⊆ 可读出集合」。

验证方式与读数

# 改前(3552ec3)
before_rowid=10**100                  -> OverflowError 穿 handler / 客户端 EOF
occurred_at=9999-12-31T23:59:59-14:00 -> OverflowError(astimezone 越界)
20000 层 JSON                          -> RecursionError 穿 handler
~1 MiB payload record_event            -> 写入成功;event_history(limit=1) 响应超限

# 改后
以上全部 -> WriteError 回执(点名原因)
大 payload record_event / propose -> WriteError + 回滚(0 行)
小 payload -> 正常写入 + 读回

python -X utf8 tests/test_issue1106_structure_service_bounds.py            # 通过 10 / 失败 0
python -X utf8 tests/test_issue1106_structure_service_bounds.py --mutate   # 3 条变异各自恰好命中
# 基线对照(origin/main 两个文件):通过 2 / 失败 8
python -m pytest tests/test_structure_*.py -q   # 49 passed, 2 skipped
实测 未改基线 3552ec3 本分支
occurred_at 时区越界 OverflowError 穿 handler WriteError 回执
深层 JSON RecursionError 穿 handler WriteError 回执
深层响应 RecursionError 穿 handler WriteError 回执
~1 MiB payload 写入 成功、读取超限 WriteError + 回滚(0 行)
小 payload(对照) 正常 正常

具名反面对照(--mutate)

  • M1 撤 dispatch 的 except (OverflowError, RecursionError) ⇒ A01 + E02 红。
  • M2 撤 _require_readable([item], "event") ⇒ B01 + E01 红(大 payload 写入成功)。
  • M3 撤 _receive 的 RecursionError 捕获 ⇒ A02 红。

三条变异各自恰好命中期望红集;变异后源码字节级还原。

边界与不做项

  • 不改 1 MiB 数值本身(部署决策);只保证「可写入 ⊆ 可读出」,超限在写入前拒绝并回滚。
  • 不覆盖既有超限数据:修复前已写入的超大记录仍可能读取超限(_send 会返回小错误回执,不再静默断连)。
  • 未测:Linux/WSL 复跑(本机 Windows 读数);完整 mTLS 起服务(守卫直接测 dispatch/_receive/_send 与 writer 事务回滚);全量 CI。

Fixes #1106

- event_history/structure_history:limit 必须是 1..200 整数(bool 也拒),
  before_rowid/before_revision 必须是正整数或 None;不再让 SQLite 类型序把
  字符串游标判为恒真(静默回第一页)、NaN 绑 NULL、超大整数 OverflowError。
- get_proposal/target_status/approve/review 的 id/aggregate_key 过 _text;
  review(note=None)、propose(event_id='')、record_version_result(instance_id=123)
  等不再穿透成 sqlite3.IntegrityError/ProgrammingError。
- load_service 的 grant 解析提取为 _parse_grant:capabilities/instances 必须是
  字符串数组;字符串不再被 frozenset() 拆成单字符集(授权面反转),缺字段/
  非数组启动即拒(fail-closed)。
- 新增 tests/test_issue1107_structure_service_validation.py:24 断言 + 3 定点变异;
  基线 2/24、修复后 24/24;structure 相关回归 49 passed / 2 skipped。
- dispatch 捕获 OverflowError/RecursionError(都不是 ValueError 子类)并转
  WriteError;_receive 捕获深层 JSON 的 RecursionError、非法 JSON;_send
  捕获深层响应的 RecursionError——不再让业务异常穿过 handler 静默关连接。
- structure_writer 新增 _require_readable:record_event/propose 在事务内按
  读取视图估算响应尺寸,超过 MAX_RECORD_BYTES(1 MiB − 4 KiB)即 WriteError
  并回滚,保证「可写入集合 ⊆ 可读出集合」。
- 新增 tests/test_issue1106_structure_service_bounds.py:10 断言 + 3 定点变异;
  基线 2/10、修复后 10/10;structure 回归 49 passed / 2 skipped。
@FuRongJun-1999

Copy link
Copy Markdown
Owner

维护侧处置(值守第 147 轮)

你的修复已采纳并以镜像方式合并:PR #1155(合并提交 0c1ca2e)——三处异常边界与 _require_readable 均为你的净增量原样(署名与致谢见 #1106 关闭帖)。

未直接合并 #1150 的原因:你的分支基线早于维护侧 #1138/#1143/#1146/#1153/#1154,直接合并会回退已合工作——已按净增量摘取重放到最新 main 之上。

本端读数:你的守卫在镜像分支 10/10;基线 3 钉红(鉴别力);structure 邻接 33 passed 无回归;CI 4/4 绿。

感谢高质量修复——「合法 JSON 触发 OverflowError」的现象甄别与「写入前按读取视图校验尺寸」的对称性修法都很到位。

@FuRongJun-1999

Copy link
Copy Markdown
Owner

净增量已镜像合并(PR #1155,0c1ca2e)——本 PR 关闭以避免与已落地内容重复。感谢贡献。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants