边界用例测试文件 — 损坏、截断、空文件与类型错标
36 个文件 · 直链下载 · 无广告 · 可自由使用
本库的其他部分回答的是“给我一个有效的 PNG”。本页回答一个更难的问题:当文件被截断、为空、名称错误、谎报类型,或者夹带了不该有的数据时,你的代码会怎么处理?这些才是真正会出现在生产环境中的上传,而手工构造它们又足够繁琐,所以大多数测试套件干脆从来不测。
这里的每个文件都是安全的。没有 zip 炸弹,没有路径穿越条目,没有可执行文件,也没有恶意软件测试字符串;最大的压缩包解压后也不到 1 MB。故障模式是真实的,载荷却没有危险,并且公布了每个文件的 SHA-256,方便你将其固定为测试夹具。
.jpg 的 HTML 文件能告诉你,图片上传是否会在你的域名上变成存储型跨站脚本(XSS)。带公式载荷的 CSV 能告诉你,你导出的数据在同事的电子表格中是否会变成可执行的公式。这两个文件最常发现真正的 bug。空文件和近乎为空的文件
零字节上传是最容易被遗忘的情况。检查文件大小上限的验证逻辑常常忘了下限,而在检查长度之前就读取第一个字节的代码会在这里直接崩溃,而不是返回一个干净的错误。
截断和损坏的文件
这些文件的头部有效,但数据不完整或已损坏——中断的上传实际上就是这个样子。信任头部并以流方式读取剩余数据的代码会在这里失败,而失败的位置能告诉你,错误处理是否真的在你以为的地方。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
truncated.png | PNG 签名和 IHDR 都有效,但在图像数据中途被截断。解码器在这里会报错,而不是返回部分图像。 | 4 KB | 下载 |
corrupt-crc.png | 长度完整、结构正确,但图像数据中有一个字节被翻转,存储的 CRC 因而对不上。严格的解码器会拒绝它;宽松的解码器会返回错误的像素。 | 9 KB | 下载 |
truncated.jpg | 在 60% 处被截断的 JPEG,没有图像结束标记。许多解码器会返回部分解码的图像而不是报错,值得弄清楚你用的解码器属于哪一种。 | 603 B | 下载 |
truncated.zip | 中央目录被截断,压缩包上传到一半中断时就是这个样子。这是现实中最常见的损坏 ZIP。 | 3 KB | 下载 |
malformed.json | 包含尾随逗号、未加引号的键和未闭合的花括号。用于测试解析器能否报告有用的出错位置,而不是笼统的失败。 | 136 B | 下载 |
谎报类型的文件
扩展名说的是一回事,字节内容却是另一回事。如果你的上传处理程序相信扩展名或浏览器提供的 Content-Type,这些文件就能蒙混过关。其中最要紧的是那个命名为 .jpg 的 HTML 文件:以图片内容类型返回时它无害,但如果从你的域名以 HTML 形式返回,就是存储型跨站脚本(XSS)。
元数据与隐私
直接从手机导出的照片会带有拍摄地点和朝向信息。不清除前者,就会泄露用户的位置;忽略后者,所有竖拍照片都会横过来显示。这个文件两者都有,方便你验证处理流程是否都处理到位。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
exif-gps-orientation.jpg | 带有 GPS 坐标(多伦多 CN 塔)和 Orientation 6,即需要顺时针旋转 90 度才能正向显示。可用它同时验证你是否清除了位置数据、是否遵循了旋转信息。 | 1 KB | 下载 |
文本、编码和换行符
在第一列变成可见字符的字节顺序标记(BOM)、包含逗号和实际换行的带引号字段、同一文件中三种不同的换行符,以及末尾没有换行符。这些在真实用户发来的文件中都再平常不过。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
bom-crlf-quoted.csv | 包含 UTF-8 字节顺序标记(BOM)、CRLF 行结束符、含逗号的带引号字段、转义的双引号、字段内的实际换行以及非 ASCII 姓名。如果 BOM 出现在你的第一列列名里,那就是 bug。 | 180 B | 下载 |
unicode-torture.txt | 包含组合字符、零宽空格、从右到左覆盖符、辅助平面字符和一个由六个码位组成的旗帜 emoji。用于测试长度计算、截断和规范化。 | 565 B | 下载 |
mixed-line-endings.txt | 同一文件中混有 LF、CRLF 和单独的 CR,最后一行没有行结束符。行计数代码在这里经常自相矛盾。 | 107 B | 下载 |
no-trailing-newline.txt | 结尾没有换行符。不加检查就往这个文件追加内容,会让两条记录连成一条。 | 48 B | 下载 |
棘手的文件名
要测试的是文件名,而不是内容。过长的文件名会撑爆数据库字段和文件系统的长度限制;非 ASCII 文件名会搞坏 Content-Disposition 头、URL 转义,还会暴露 macOS 上 Unicode 组合形式与分解形式的差异。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
文件名-with spaces-🌲.txt | 文件名包含中文、空格和 emoji。用于测试 Content-Disposition 编码、URL 转义以及 macOS 的 Unicode 分解形式规范化。 | 194 B | 下载 |
结构与资源限制
这些文件合法,只是难对付,并没有损坏:一个含一万个条目的压缩包、嵌套层级超过大多数解析器默认上限的 JSON,以及一个加密压缩包。它们都不是攻击——只是会让简单粗暴的实现耗尽某种资源的文件形态。
电子表格公式注入
以 =、+、- 或 @ 开头的 CSV 单元格,在 Excel、Google 表格或 LibreOffice 中打开时会被当作公式执行。如果你的应用把用户提供的文本导出为 CSV 时没有转义这些前缀,你就是在把用户输入当作可执行公式发出去。这里的载荷只做无害的算术运算。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
formula-injection.csv | 以 =、+、- 和 @ 开头的单元格,电子表格应用会把它们当作公式处理。这些载荷只做无害的算术运算,其中一个会生成指向本站的链接。不会执行任何命令。 | 189 B | 下载 |
3D 模型:空的、损坏的和误导性的网格
网格处理代码往往假定模型是封闭的、尺寸合理的、绕序正确的,并且至少有一个三角形。而用户什么样的都会上传。这些文件涵盖:空网格、零面积和法线反向的三角形、非流形网格、对 float32 来说过大或过小而难以妥善处理的坐标、上传中途被截断的 GLB、头部谎报数据的 STL、伪装成 STL 的 GLB,以及会骗过经典的“以 solid 开头就是 ASCII”判断的二进制 STL。它们位于 3D 文件夹下;有效的 3D 示例在 3D 模型分类中。
| 文件 | 测试内容 | 大小 | 获取 |
|---|---|---|---|
empty-mesh-zero-triangles.stl | 结构有效的二进制 STL:只有 80 字节的文件头和为 0 的三角形数量,别无其他(84 字节)。计算包围盒、居中和生成缩略图的代码在这里经常会除以零或访问空数组。 | 84 B | 下载 |
empty-scene-no-meshes.glb | 有效的 glTF 2.0 二进制文件,含一个场景和一个空节点,但没有网格、缓冲区或材质。它能通过 Khronos 验证器。查看器应显示空场景,而不是抛出异常。 | 276 B | 下载 |
degenerate-triangles.stl | 一个 10 mm 立方体外加六个面积为零的三角形:重复顶点、共线点和一个小于 epsilon 的细长三角形。计算法线时这里会除以零长度,NaN 法线正是这样来的。 | 984 B | 下载 |
flipped-normals-inside-out.stl | 一个 10 mm 立方体,所有三角形都按顺时针绕序,存储的法线也全部朝内。开启背面剔除时它会渲染成黑色或完全不可见,其有向体积为负。 | 684 B | 下载 |
non-manifold-open-box-and-fins.stl | 一个缺了顶面的盒子(开放边界),外加两片鳍片,每片都与另外两个面共用一条边。原样无法打印;切片软件和修复工具应当把这两个问题都标记出来。 | 684 B | 下载 |
huge-coordinates-1e7.stl | 一个边长 100 单位的立方体,中心距原点一千万单位。在这个量级上 float32 只能表示整数,因此精度、相机远裁剪面和自动取景的问题都会暴露出来。 | 684 B | 下载 |
tiny-scale-1e-6.stl | 一个边长为百万分之一单位的立方体。按毫米解读就是一微米:用于测试最小尺寸检查、单位推断以及合并顶点时使用的 epsilon。 | 684 B | 下载 |
extreme-float-values.stl | 顶点坐标为 ±3.0e38,接近 float32 的最大值,另有一个由 1e-40 次正规数构成的三角形。文件中没有 NaN 或 Infinity,但用 float32 计算包围盒尺寸会溢出为 Infinity。 | 234 B | 下载 |
truncated.glb | 一个有效的带纹理 GLB 的前 60%。文件头仍声明完整长度,而 BIN 块提前结束,GLB 上传中断时就是这个样子。 | 80 KB | 下载 |
wrong-triangle-count-header.stl | 一个二进制 STL,其 uint32 计数声称有 1,000 个三角形,而文件实际只有 12 个。信任该计数的读取器会读到文件末尾之外;严格的读取器会拒绝该文件,因为 84 + 50 × 1,000 与文件大小不符。 | 684 B | 下载 |
actually-a-glb.stl | 一个货真价实的有效 GLB(以字节 glTF 开头),却以 .stl 扩展名保存。凡是按扩展名分派处理的代码,都会把它交给 STL 解析器。 | 21 KB | 下载 |
binary-stl-header-starts-with-solid.stl | 一个有效的二进制 STL,其自由文本文件头以单词 solid 开头,有几款真实的导出工具就是这么写的。靠这个前缀识别 ASCII STL 会把它交给错误的解析器;应改为将文件大小与三角形数量进行比对。 | 684 B | 下载 |
obj-missing-mtl.obj | 一个除此之外完全有效的 OBJ,其 mtllib 行引用了一个不存在的材质文件。几何体仍应以默认材质加载并给出警告,而不是失败。 | 914 B | 下载 |
obj-negative-indices.obj | 一个有效的 OBJ,其面使用负的相对索引(f -3 -2 -1),这是格式本身允许的。许多手写解析器只支持正索引。 | 675 B | 下载 |
立方体 cube-modèle-🧊.stl | 一个有效的 10 mm 立方体,文件名混合了中文、带重音的字母、空格和 emoji。用于测试模型上传时的 Content-Disposition、URL 编码和存储键名。 | 684 B | 下载 |
上传处理简明检查清单
- 既要检查最大值,也要检查最小值。零字节上传是最常被遗漏的情况。
- 根据文件字节判断类型,切勿依据扩展名或浏览器提供的内容类型。这两者都可被攻击者控制。
- 从单独的域名提供用户上传的文件,或加上
Content-Disposition: attachment和X-Content-Type-Options: nosniff,这样即使文件实际上是 HTML,也无法在你的源中执行。 - 发布图片前去除 EXIF,并在去除之前先应用方向标签。
- 将用户文本写入 CSV 时,对开头的
=、+、-和@进行转义。 - 为压缩包条目数量、解压后的总大小和解析器递归深度设置明确的上限,触发上限时返回清晰的错误信息。
- 想清楚上传不完整的文件应该如何处理,然后用这里的截断文件实际测试,而不是想当然。
常见问题
这些文件危险吗?
不危险。没有 zip 炸弹,没有路径穿越条目,没有可执行文件,没有宏,也没有恶意软件测试字符串。最大的文件解压后也不到 1 MB。故障模式是真实的——截断的图片确实是截断的——但这里没有任何东西会攻击打开它的机器。电子表格公式载荷只计算无害的算术,不会执行命令。
带 .jpg 扩展名的 HTML 文件有什么用?
它是整个包里最有价值的文件。如果你的应用把它当作图片接受并保存,之后又根据内容猜测的内容类型把它返回,浏览器就会把它作为你域名下的页面渲染出来。这就是通过图片上传实现的存储型跨站脚本。接受这个文件没有问题;把它当作 HTML 返回才是问题。
为什么这个 CSV 里有以等号开头的单元格?
因为 Excel、Google Sheets 和 LibreOffice 会把以 =、+、- 或 @ 开头的单元格当作公式。如果你的应用把用户提交的文本导出为 CSV 而没有转义这些前缀,用户在表单中输入的任何内容都会以可执行公式的形式出现在同事的电子表格里。解决办法是在导出时给这类单元格加上撇号前缀,或用引号包起来。
这张照片真的包含 GPS 坐标吗?
是的——多伦多的 CN 塔,北纬 43.6426、西经 79.3871,另有海拔数据。它还带有方向值 6,表示查看器应将其顺时针旋转 90 度才能正立显示。这两项覆盖了每个图片处理流程都必须做对的两件事:发布前去除位置数据,并遵循旋转信息,避免竖拍照片显示成横的。
可以在自动化测试套件中使用这些文件吗?
可以,它们正是为此而做。每个文件都是确定性的,SHA-256 公布在本页,直链带有较长的缓存时间和开放的 CORS 头。在测试中固定哈希值,一旦某个测试夹具发生变化,你会立即知道。
发现问题,或者觉得哪里可以更好?每条消息我们都会阅读,并尽快修复。
需要正常文件?
大多数测试需要的是能正常使用的文件。这些我们也提供——真实的图片、视频、音频、文档、压缩包、数据、字体和 3D 模型,尺寸精确,并公布哈希值。