|
|
c59ecd6dbb
|
fix(SQL 沙箱 Minor): 让题目的 memoryLimit 对学生真正生效
## M-1
题目写 64MB 也没意义 —— 唯一的硬顶是子进程那个固定 512MB 的 ulimit -d,
学生实际能吃到 8 倍。旧实现是 setlimit(SQLITE_LIMIT_LENGTH, memoryLimit)
把单值长度贴着题目内存限,但 sql.js 的 wasm 没导出 sqlite3_limit(已核对导出表),
复刻不了。
改成引擎侧按字节记账(ByteBudget):取行时累加,单值超限或结果集累计超限都按 MLE 拒。
max_page_count 管的是库文件页数,管不住「一个 SELECT 拼出一个巨大的值」,所以两者
不重复。查询题和增删改题(dumpTables)两条路都记账,受信脚本不记。
实测 6 条,关键是**同一句 SQL 在 4MB 的题上被拦、在 64MB 的题上放行**,
证明限制跟着题目走而不是一刀切。
第一版测试用的是 100MB 的值,结论是错的:wasm 堆触顶时的兜底和我的记账器报的是
同一句「单个数据值超出内存限制」,大值根本分不清是谁拦的。换成 8MB 才测得准。
这个教训写进注释了。
M-1 的第二半(max_page_count 学生可自行调大)在 I-1 拦 PRAGMA 时已一并修掉。
## M-3
阶段 5 的分阶段兜底超时顺带解决:出题人预览死循环从 25s 降到 13005ms 实测。
## M-2 不修
「强制两个测试点期望结果不同」会把合法出题也挡掉(刻意用两组数据验证同一边界、
结果恰好相同),代价是老师被一条看不懂的错误拦住。评审也确认与旧实现一致、非回归。
更合适的是提示而非拒绝,但要动契约和后台前端。理由写进评审文档,免得下次又当新发现。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-08-08 02:27:35 -06:00 |
|
|
|
0f94e7ecbd
|
fix(阶段4): 两份独立安全评审的 Critical/Important 全部修掉
## 权限边界评审(后台 86 个 handler)
守卫本身一个没漏,问题全在对象级归属校验:
- C1 跨题单删奖章:先按 (id, problemsetId) 校验奖章归属再删,
否则拿自己的题单 id + 别人的奖章 id 就能把别人的 user_badge 删掉
- C2 make-public 无归属校验:补 canEdit,越权者拿不到题面
- I1 两个分析端点被 `/problems/:id` 遮蔽 —— Hono 按注册顺序匹配,
不是静态优先。挪到 `/problem-analytics/*`
- I2 from-public 只校验目标比赛归属:源题也必须是公开题库题
- I3 克隆比赛回传原比赛明文密码:克隆一律 password: null
- I4 upload-image 守卫比旧后端严,教师写题面会 403:收回 requireAdmin
两个互不可见的教师账号实跑复验,六条全部拦住。
## SQL 判题沙箱评审
- I-1 查询题只读被一句 `PRAGMA query_only=0` 关掉,实测 DML 拿到 AC。
query_only 自己就是个 PRAGMA,旧实现靠 authorizer 把 SQLITE_PRAGMA
一律拒了才没这个洞。现在 runStudent 逐语句拦 PRAGMA(用
sqlite3_normalized_sql 判关键字,注释和大小写由 SQLite 抹平),
并在每条语句前重放 query_only 和 max_page_count 兜底。
顺带修掉 M-1 里 max_page_count 学生可自行调大的部分。
- I-2 单条语句进了 step() 就打断不了,只能等父进程 SIGKILL,
而兜底时限是整个作业一口价 25s —— 1s 限的题要 26s 才判 TLE,
判题池只有 2 个槽,几发死循环就能把所有人堵住。
改成分阶段:子进程用 stderr 报 prepare/student/display,
父进程边读边换表,一进学生 SQL 就把兜底收到「题目时限 + 2s」。
实测 26s → 3.06s。
归因也跟着修了:卡在受信脚本(出题人的初始化脚本、标准答案)
现在报 SYSTEM_ERROR,不再当成学生超时甩 TLE。
engine.ts 头部那张防护对照表按实测重写 —— 原来那版把 query_only
写成等价于 authorizer 白名单,是不成立的。另记一笔:stock sql.js 的
wasm 没导出 progress_handler / interrupt / set_authorizer / limit,
想要得自己编,别再去翻了。
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
2026-08-07 21:59:42 -06:00 |
|