如果你在Windows上分发一个.yymps(或任何资产压缩包)并且你在Windows上构建它,那么这需要花费你2分钟的时间。如果我分发了4个包含路径分隔符错误的包,并且3个独立的检查都告诉我它们是好的。
问题
压缩包存储一个路径/条目,每个条目都有一个路径,规范要求使用斜杠。PowerShell的 Compress-Archive 和 .NET的 ZipFile.CreateFromDirectory 都写入了反斜杠。
在Windows上,这是不可见的,文件会正常打开。在macOS和Linux上,解压器不会将 \ 当作分隔符,所以用户可以得到一个完全扁平的文件,文件名为 Meridian\scripts\mer_tree\mer_tree.gml。我有21个条目在一个包中使用了反斜杠,85个条目在4个包中使用了反斜杠。
为什么我没有发现它,实际上是最有用的部分
我使用Python的 zipfile.namelist() 进行了审计。它报告了整个前向斜杠。有两个其他人检查了它。他们使用了相同的工具。他们都确认了正常。三个独立的“确认”实际上是同一个盲目工具穿着三个不同的面具。 namelist() 无法 在Windows上报告此问题。 在CPython中, ZipInfo.__init__ 做了:如果 os.sep 不等于 / 并且 os.sep 在 filename 中,则 filename = filename.replace(os.sep, "/") 和 _RealGetContents 构建了每个条目通过 ZipInfo。因此,存储的反斜杠在读取时被标准化,发生在创建bug的exact平台上。 这不是Python的bug,标准化正在执行其职责。只是发生在你需要原始字节的地方。 读取中心目录直接: b'Project\LICENSE.txt' ->原始文件中出现的次数:2 b'Project/LICENSE.txt' ->原始文件中出现的次数:0 zipfile.namelist() 说:Project/LICENSE.txt 前向斜杠形式在文件中根本不存在。
如何实际检查
任何读取字节而不是标准化视图的工具: * unzip -l yourfile.yymps 在macOS/Linux/WSL上,分隔符显示为存储的 * 7-Zip: 7z l -slt yourfile.yymps * 或者扫描中心目录条目名称中的原始字节中的反斜杠 不要在Windows上使用 zipfile.namelist() 进行检查,也不要假设 .NET 是安全的。 我以前通过交换 Compress-Archive 为 ZipFile.CreateFromDirectory 来“修复”这个问题,但这并没有改变什么,我盲目的验证工具确认了非修复。 在一个两层深的测试树上,读取原始中央目录字节: | 写入器 | raw反斜杠 | raw前向斜杠 | namelist()报告的内容 | |:-|:-|:-|:-| |PowerShell Compress-Archive|1|0|0| |.NET ZipFile.CreateFromDirectory|1|0|0| |in-process zip writer (Node)|0|1|0|
修复
使用控制条目名称的工具写入压缩包,或者后处理它们。 我切换到了一个在进程中运行的写入器,它设置每个条目名称并且然后重新读取压缩包自己的中心目录来验证之前允许它离开。 验证后:24个条目,0个反斜杠。
一个元学习成本最多的经验教训:
我写的脚本用来 证明 缺陷也使用了 namelist()。所以它找到了零,它的“复制”分支从未运行,它打印了“确认:写入前向斜杠”(事实上是错误的)并且在其自己的失败路径上退出。它看起来像是一个通过。它现在断言缺陷复制,好写入是干净的,并且 namelist() 对第一个是盲目的,除非三者都成立,它才退出非零。 如果你的验证工具从未失败,你就没有验证它。
披露: 我使用AI辅助(Claude)构建GameMaker资产并销售它们,这是出于分发其中一个而产生的发现。发现是引擎无关的,并适用于任何在Windows上打包任何内容的人。 如果有用,我愿意分享原始中央目录扫描,它大约有30行。
评论 (0)