运行时文件 Base64 填充¶
带填充的运行时文件写入长度必须能被四整除。空字符串以及长度模四等于零、二或三的无填充 Base64 仍然有效。 此更改恰好拒绝此前被接受的、包含尾部填充且总长度模四为二或三的字符串。它不强制规范化的未使用填充位,也不更改字母表。
边界证据¶
| 输入 | 之前 | 之后 |
|---|---|---|
A= |
接受 | 拒绝 |
AA== |
接受 | 接受 |
AAA= |
接受 | 接受 |
AAAA |
接受 | 接受 |
'' |
接受 | 接受 |
A |
拒绝 | 拒绝 |
== |
接受 | 拒绝 |
AA=A(内部填充) |
拒绝 | 拒绝 |
AA= |
接受 | 拒绝 |
A== |
接受 | 拒绝 |
AAAA== |
接受 | 拒绝 |
AA、AAA(无填充) |
接受 | 接受 |
Buffer.from('A=', 'base64') 解码为零字节。在 RPC 边界拒绝格式错误的填充,可防止一个被接受的请求静默写入不同的字节。
调用方普查¶
| 调用方 / 接口面 | 可达性与兼容性结论 |
|---|---|
桌面端 runtime-file-import-client.ts → uploadRuntimeFileWithoutClobber → writeRuntimeBase64File |
files.writeBase64 和 files.writeBase64Chunk 的唯一生产环境生产者。filesystem-runtime-upload-staging.ts 中的暂存使用 buffer.toString('base64') 编码完整文件;新拒绝的值无法被生成。 |
| 桌面端单帧上传 | 当暂存字符串长度最多为 512 × 1024 个字符时,原样发送该字符串。标准 Node Base64 的长度始终能被四整除。空文件仍被接受。 |
| 桌面端分块上传 | 在 512 × 1024 = 524,288 个字符处切分编码流,该长度能被四整除。每个偏移量和每个完整分块都与四元组对齐。最后一个分块是两个四的倍数之差,即使它以 = 或 == 结尾也是如此。不会额外组装最后一个分块,也不会添加逐分块填充。 |
stageExternalPathsForRuntimeUpload 的 Web 实现 |
返回空源列表;不会生成文件写入负载。 |
| 移动端文件编辑器 | 使用 files.writeTerminalArtifact 配合文本内容及其独立模式。不会到达此谓词。 |
| 移动端剪贴板 / 图片附件 | 使用 clipboard.startImageUpload、clipboard.appendImageUploadChunk、clipboard.commitImageUpload 以及 clipboard.saveImageAsTempFile 回退。它们的验证器是 clipboard-params.ts 中的 isValidBase64,而不是 isValidRuntimeFileBase64。保持不变,包括移动端规范化器现有的宽松填充行为。 |
| CLI | 没有任一 Base64 文件写入方法的生产者。src/cli/handlers/file.ts 中的文件命令调用 files.open / files.openDiff;其他 CLI RPC 调用点不会构造 Base64 文件写入。 |
| 生成的参数目录 | 引用两个模式;RpcParams 消费者使用推断类型。移动端的入口点仅为 export type,因此不会发生新的客户端解析。 |
| RPC 分发 | files-mutation-methods.ts 注册两个模式。分块模式扩展整个文件模式;这些是该谓词唯一的运行时消费者。直接运行时/提供者调用不会解析这些模式。 |
| 调用方 / 接口面 | 可达性与兼容性结论 |
|---|---|
仓库范围的搜索覆盖了方法名、模式名、谓词及其模式,以及上传/暂存函数的所有调用方。针对 HEAD 在 mobile/src 下的定向历史搜索未发现受影响方法或谓词的引入/移除。本地发布引用 mobile-ios-v0.0.27 和 mobile-v0.0.13 也不包含任一 Base64 文件写入方法的调用方;iOS 引用使用了上述独立的剪贴板和终端产物方法。本次源码/历史审计未发现已发布的移动端生产者会生成新被拒绝的值。
远程与工作区兼容性¶
使用受审计生产者的旧桌面客户端会向新主机发送有效四元组。新客户端仍会向旧主机发送相同字节。方法、字段、操作码或主机发布的内容均未发生变化。这遵循 remote-wire-compatibility.md 中的混合版本要求。
RPC 验证在工作区解析和提供者选择之前运行,因此相同规则适用于文件夹工作区、git worktree、本地主机和 SSH 主机。SSH 所有权围栏和提供者写入保持不变。任意发送格式错误填充的外部 RPC 调用方现在将收到验证错误;有效的填充和无填充负载仍会被接受。
回归证据¶
src/main/runtime/rpc/methods/files-base64-padding.test.ts 验证了两个实际 RPC 注册,断言被拒绝的输入永远不会到达写入器,并验证被接受的内容原样转发。使用原始谓词时,测试运行产生了 16 个失败 / 16 个通过;全部 16 个失败都是旧实现接受的新被拒绝的填充形状。这是在编辑谓词之前运行的。
现有的桌面外部导入测试现在在 524,288 字符的首个块之后使用最终的 AA== 块,固定真实上传路径中填充最终块的转发。无需更改生产者或剪贴板验证。
验证结果¶
所有测试/类型检查命令均使用 ORCA_BACKGROUND_LAUNCH=1。
pnpm tc:退出码 0;所有根类型检查项目通过。pnpm exec vitest run src/main/runtime/rpc:277 个文件通过,1 个失败; 2,419 个测试通过,2 个超时,1 个跳过。两个超时都位于未更改的terminal-output-frame-chunks-equivalence.test.ts中(5 秒代理范围测试和 30 秒 800 负载模糊测试)。pnpm --dir mobile typecheck:退出码 0(tsc --noEmit)。pnpm run check:code-quality:changed:退出码 0;代码质量、类型感知代码 质量和 React Doctor 在三个源文件中均报告零新增发现。- 使用
--config config/vitest.config.ts --maxWorkers=2的聚焦运行:全部三个 文件 / 58 个测试通过,覆盖填充、桌面外部导入,以及初始运行中超时的 终端输出等效文件。 - 使用
--maxWorkers=2的完整 RPC 重跑:退出码 0;全部 278 个文件通过, 2,421 个测试通过,1 个跳过(198.34 秒)。无需超时覆盖。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 orca48/orca