feat(阶段4): 测试用例压缩包上传与下载
POST admin/test-cases GET admin/problems/:id/test-cases (返回 zip 二进制) 落盘格式必须与判题沙箱镜像的约定一致(沙箱直接读挂进去的目录),已用真判题验证: 上传 zip → 建题 → 提交 Python 解法 → 沙箱读到用例并判出 Accepted。 安全与健壮性上比旧后端多做的几件事: - **zip slip 从设计上进不来**:不遍历压缩包条目,只按精确文件名(`N.in`/`N.out`/`N.sql`) 取内容,条目名一律不参与路径拼接。实测带 `../../etc/passwd` 条目的包能正常处理, 且只取到 1.in/1.out。 - 单文件 32MB、解压后总量 128MB、测试点数 500 的上限,防 zip bomb 与写满磁盘 —— 旧后端一概没有,机房那台机器盘写满之后判题也会一起挂。 - 坏 zip 返回 400 而不是 500。 对齐旧后端的细节:CRLF→LF 归一;`stripped_output_md5` 按 Python `bytes.rstrip()` 的口径只剥尾部 ASCII 空白后再算(实测与 hashlib.md5 结果一致);编号从 1 起连续、 遇缺口即停;SQL 包至少 2 个测试点(题目页会展示测试点 1 的期望结果,只有一个时 学生可以对照着硬编码 AC);目录 0710、文件 0640。 ## 顺带修掉一个只在判题时才暴露的路径 bug config 里的相对路径(data/test_case、data/avatar、data/upload)原先按进程 cwd 解析, 而起服务的方式会把 cwd 切到 apps/api/,于是测试点落在 apps/api/data/ 下 —— 但 docker/compose.dev.yml 把**仓库根**的 data/test_case 挂进判题沙箱。两边不是同一个 目录,新传的测试点判题时会「找不到测试数据」,且只在真正判题时才暴露。 改成一律按仓库根解析,实测沙箱能看到新传的目录。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -212,7 +212,7 @@ export function uploadTestcases(file: File, options: { sql?: boolean } = {}) {
|
||||
if (options.sql) {
|
||||
form.append("sql", "1")
|
||||
}
|
||||
return http.post<TestcaseUploadedReturns>("admin/test_case", form, {
|
||||
return api2.post<TestcaseUploadedReturns>("admin/test-cases", form, {
|
||||
headers: { "content-type": "multipart/form-data" },
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user