エッジケースのテストファイル — 破損・途中切れ・空・拡張子偽装
36 ファイル · 直接リンク · 広告なし · 用途自由
このライブラリのほかのページは「正常な PNG がほしい」という要望に応えるものです。このページが扱うのはもっと難しい問いです:途中で切れている、空である、名前が間違っている、種類を偽っている、あるいは含むべきでないデータを含んでいる――そんなファイルを受け取ったとき、あなたのコードはどう動くでしょうか。本番環境に届くのはまさにそうしたアップロードですが、手作業で用意するのが面倒なため、ほとんどのテストスイートでは一度も試されていません。
ここにあるファイルはすべて安全です。ZIP 爆弾、パストラバーサルのエントリ、実行ファイル、マルウェアのテスト文字列は含まれておらず、最大のアーカイブでも展開後 1 MB 未満です。失敗の仕方は本物ですが、中身に危険はありません。各ファイルの SHA-256 を公開しているので、フィクスチャとして固定できます。
.jpg という名前の HTML ファイルで、画像アップロードがドメイン上の格納型クロスサイトスクリプティングにつながるかどうかがわかります。数式ペイロード入りの CSV で、エクスポートしたデータが同僚のスプレッドシートで有効な数式として開かれてしまうかどうかがわかります。実際のバグを見つけることが最も多いのはこの 2 つです。空のファイルとほぼ空のファイル
0 バイトのアップロードは、最も見落とされやすいケースです。最大サイズをチェックするバリデーターは最小サイズを忘れがちで、長さを確認する前に先頭バイトを読むコードは、きちんとエラーを返さずにここでクラッシュします。
途中で切れたファイルと破損ファイル
ヘッダーは有効でも、データが不完全だったり壊れていたりするファイルです。中断されたアップロードは実際にこうなります。ヘッダーを信用して残りをストリーム処理するコードはここで失敗し、どこで失敗するかを見れば、エラー処理が想定どおりの場所にあるかどうかがわかります。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
truncated.png | 有効な PNG シグネチャと IHDR を持ち、画像データの途中で切れています。デコーダーは部分的な画像を返すのではなく、ここでエラーを出します。 | 4 KB | ダウンロード |
corrupt-crc.png | 長さも構造も正しいものの、画像データ内の 1 バイトが反転しており、保存された CRC と一致しません。厳密なデコーダーは拒否し、寛容なデコーダーは誤ったピクセルを返します。 | 9 KB | ダウンロード |
truncated.jpg | 60% で途切れた、画像終了マーカーのない JPEG です。多くのデコーダーは失敗せずに途中までデコードした画像を返すので、自分のデコーダーがどう動くか知っておく価値があります。 | 603 B | ダウンロード |
truncated.zip | セントラルディレクトリが途切れています。アーカイブのアップロードが途中で止まるとこうなります。実際に最もよく見かける破損 ZIP です。 | 3 KB | ダウンロード |
malformed.json | 末尾のカンマ、引用符のないキー、閉じていない波かっこを含みます。パーサーが汎用的な失敗ではなく、役に立つ位置を報告するかをテストします。 | 136 B | ダウンロード |
種類を偽るファイル
拡張子とバイト列の中身が食い違っています。アップロード処理が拡張子やブラウザから送られる Content-Type を信用していると、これらは素通りします。重要なのは .jpg という名前の HTML ファイルです。画像の Content-Type で返すなら無害ですが、自分のドメインから HTML として配信すれば格納型クロスサイトスクリプティングになります。
メタデータとプライバシー
スマートフォンで撮ったままの写真には、撮影場所と画像の向きが記録されています。前者を削除しなければユーザーの位置情報が漏れ、後者を無視すれば縦向きの写真がすべて横倒しで表示されます。このファイルには両方が含まれているので、パイプラインがそれぞれを正しく処理するかを確認できます。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
exif-gps-orientation.jpg | GPS 座標(トロントの CN タワー)と、正しく表示するには時計回りに 90 度回転させることを意味する Orientation 6 を持っています。位置情報を削除しているか、回転を反映しているかの両方の確認に使ってください。 | 1 KB | ダウンロード |
テキスト、文字コード、改行コード
最初の列に見える文字として現れてしまうバイトオーダーマーク、カンマや改行そのものを含む引用符付きフィールド、1 つのファイルに混在する 3 種類の改行コード、そして末尾に改行のないファイル。どれも実際のユーザーが送ってくるファイルではごく普通のことです。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
bom-crlf-quoted.csv | UTF-8 のバイトオーダーマーク、CRLF の改行、カンマを含む引用符付きフィールド、エスケープした二重引用符、フィールド内の改行そのもの、ASCII 以外の名前を含みます。最初の列見出しに BOM が表示されたら、それがバグです。 | 180 B | ダウンロード |
unicode-torture.txt | 結合文字、ゼロ幅スペース、右から左への上書き、アストラル面の文字、6 つのコードポイントからなる国旗の絵文字を含みます。長さの数え方、切り詰め、正規化をテストします。 | 565 B | ダウンロード |
mixed-line-endings.txt | 1 つのファイルに LF、CRLF、単独の CR が混在し、最終行には改行がありません。行数を数えるコードは、ここでしばしば自分自身と矛盾した結果を出します。 | 107 B | ダウンロード |
no-trailing-newline.txt | 改行なしで終わるファイルです。確認せずに追記すると、2 つのレコードが 1 つにつながってしまいます。 | 48 B | ダウンロード |
扱いにくいファイル名
テストするのは中身ではなく名前です。長い名前はデータベースの列やファイルシステムの上限を超え、ASCII 以外の文字を含む名前は Content-Disposition ヘッダー、URL エスケープ、そして macOS での Unicode の合成形と分解形の違いで問題を起こします。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
文件名-with spaces-🌲.txt | ファイル名に漢字、スペース、絵文字を含みます。Content-Disposition のエンコード、URL エスケープ、macOS の Unicode 分解形の正規化をテストします。 | 194 B | ダウンロード |
構造とリソースの上限
壊れているのではなく、扱いにくいだけの有効なファイルです。1 万個のエントリを持つアーカイブ、多くのパーサーの既定値より深くネストした JSON、暗号化されたアーカイブがあります。どれも攻撃ではありませんが、素朴な実装では何かしらのリソースを使い果たしてしまう形です。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
many-entries-10000.zip | 1 万個の小さなエントリで、展開後の合計は 1 MB 未満です。セントラルディレクトリの解析とエントリごとのオーバーヘッドをテストします。意図的に ZIP 爆弾にはしていません。 | 1.6 MB | ダウンロード |
deeply-nested.json | 512 階層のネストです。有効な JSON ですが、多くのパーサーの既定の上限より深く、再帰的なパーサーのスタックを使い果たすほどの深さです。 | 3 KB | ダウンロード |
encrypted-password-test.zip | ZipCrypto で暗号化されており、パスワードは test です。パスワードなしの展開は、意味不明なデータを出力せずにきちんと失敗する必要があります。 | 292 B | ダウンロード |
スプレッドシートの数式インジェクション
=、+、-、@ で始まる CSV のセルは、Excel、Google スプレッドシート、LibreOffice で開くと数式として解釈されます。アプリケーションがユーザー入力のテキストを、これらの先頭文字をエスケープせずに CSV に書き出していると、その入力を実行可能な数式として配布していることになります。ここにあるペイロードは無害な計算をするだけです。
| ファイル | テスト内容 | サイズ | 入手 |
|---|---|---|---|
formula-injection.csv | 表計算アプリが数式として扱う =、+、-、@ で始まるセルを含みます。ペイロードは無害な計算を行うもので、1 つはこのサイトへのリンクを作ります。コマンドを実行するものはありません。 | 189 B | ダウンロード |
3D モデル:空のメッシュ、壊れたメッシュ、紛らわしいメッシュ
メッシュを扱うコードは、閉じていて、サイズが妥当で、面の向きが正しく、三角形が 1 つ以上あるモデルを前提にしがちです。しかしユーザーはそれ以外のあらゆるものをアップロードします。ここでは、空のメッシュ、面積 0 の三角形と裏返った三角形、非多様体メッシュ、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 | シーンと空のノードが 1 つずつあるものの、メッシュ、バッファ、マテリアルを持たない有効な glTF 2.0 バイナリです。Khronos のバリデーターに合格します。ビューアーは例外を投げずに空のシーンを表示すべきです。 | 276 B | ダウンロード |
degenerate-triangles.stl | 10 mm の立方体に、面積ゼロの三角形を 6 つ加えたものです(重複した頂点、同一直線上の点、イプシロン未満の細長い三角形)。法線の計算でここで長さゼロによる除算が起き、NaN の法線はここから生まれます。 | 984 B | ダウンロード |
flipped-normals-inside-out.stl | すべての三角形が時計回りで、保存された法線が内側を向いている 10 mm の立方体です。背面カリングがあると真っ黒か見えない状態で描画され、符号付き体積は負になります。 | 684 B | ダウンロード |
non-manifold-open-box-and-fins.stl | 上面のない箱(開いた境界)に、それぞれ 1 本の辺を他の 2 つの面と共有するフィンを 2 枚加えたものです。このままでは印刷できず、スライサーや修復ツールは両方の問題を指摘すべきです。 | 684 B | ダウンロード |
huge-coordinates-1e7.stl | 原点から 1,000 万単位離れた位置を中心とする 100 単位の立方体です。この大きさでは float32 は整数しか表せないため、精度、カメラのファープレーン、自動フレーミングの問題がすべて現れます。 | 684 B | ダウンロード |
tiny-scale-1e-6.stl | 差し渡し 100 万分の 1 単位の立方体です。ミリメートルとして読むと 1 マイクロメートルで、最小サイズのチェック、単位の推測、頂点の結合に使うイプシロンをテストします。 | 684 B | ダウンロード |
extreme-float-values.stl | 頂点座標が float32 の最大値に近い ±3.0e38 で、非正規化数 1e-40 の値でできた三角形を含みます。ファイルに NaN や Infinity はありませんが、float32 でバウンディングボックスのサイズを計算すると Infinity にオーバーフローします。 | 234 B | ダウンロード |
truncated.glb | 有効なテクスチャ付き GLB の先頭 60% です。ヘッダーは完全な長さを主張したままで、BIN チャンクが途中で終わっています。GLB のアップロードが中断されるとこうなります。 | 80 KB | ダウンロード |
wrong-triangle-count-header.stl | uint32 の三角形数が 1,000 となっているのに、実際には 12 個しかないバイナリ STL です。数を信用するリーダーはファイルの終わりを越えて読み、厳密なリーダーは 84 + 50 × 1,000 がファイルサイズと一致しないためファイルを拒否します。 | 684 B | ダウンロード |
actually-a-glb.stl | 本物の有効な GLB(先頭のバイトは glTF)を、拡張子 .stl で保存したものです。拡張子で処理を振り分けるものは、これを STL パーサーに渡してしまいます。 | 21 KB | ダウンロード |
binary-stl-header-starts-with-solid.stl | 自由記述のヘッダーが solid という単語で始まる有効なバイナリ STL で、実際にいくつかのエクスポーターがこう書き出します。この接頭辞で ASCII STL を判定すると、このファイルは誤ったパーサーに送られます。代わりにファイルサイズと三角形数を比較しましょう。 | 684 B | ダウンロード |
obj-missing-mtl.obj | mtllib の行が存在しないマテリアルファイルを指していること以外は有効な OBJ です。失敗するのではなく、ジオメトリは既定のマテリアルと警告付きで読み込まれるべきです。 | 914 B | ダウンロード |
obj-negative-indices.obj | 面に、形式上許されている負の相対インデックス(f -3 -2 -1)を使う有効な OBJ です。手書きのパーサーの多くは正のインデックスにしか対応していません。 | 675 B | ダウンロード |
立方体 cube-modèle-🧊.stl | ファイル名に漢字、アクセント付き文字、スペース、絵文字が混在する、有効な 10 mm の立方体です。モデルのアップロードにおける Content-Disposition、URL エンコード、ストレージのキーをテストします。 | 684 B | ダウンロード |
アップロード処理の簡単なチェックリスト
- 最大サイズだけでなく最小サイズも確認する。0 バイトのアップロードは最も見落とされやすいケースです。
- ファイルの種類は、拡張子やブラウザが送る Content-Type ではなく、必ずバイト列から判定する。どちらも攻撃者が自由に操作できます。
- ユーザーがアップロードしたファイルは別ドメインから配信するか、
Content-Disposition: attachmentとX-Content-Type-Options: nosniffを付けて配信する。そうすれば、中身が HTML だったファイルが自分のオリジンで実行されることはありません。 - 画像を公開する前に EXIF を削除する。削除する前に Orientation タグを反映させておく。
- ユーザーの入力テキストを CSV に書き出すときは、先頭の
=、+、-、@をエスケープする。 - アーカイブのエントリ数、展開後の合計サイズ、パーサーの再帰の深さに明示的な上限を設け、上限に達したらわかりやすいエラーを返す。
- 途中までしかアップロードされなかったファイルをどう扱うかを決め、思い込みに頼らずここにある途中切れのファイルでテストする。
よくある質問
これらのファイルは危険ではありませんか?
危険ではありません。ZIP 爆弾、パストラバーサルのエントリ、実行ファイル、マクロ、マルウェアのテスト文字列は含まれていません。最大のファイルでも展開後 1 MB 未満です。失敗の仕方は本物(途中で切れた画像は実際に切れています)ですが、開いたマシンを攻撃するものは何もありません。スプレッドシートの数式ペイロードも、コマンドを実行するのではなく無害な計算をするだけです。
拡張子が .jpg の HTML ファイルは何のためのものですか?
このパックの中で最も価値のあるファイルです。アプリケーションがこれを画像として受け付けて保存し、後で中身から推測した Content-Type で配信すると、ブラウザはそれをあなたのドメイン上のページとして表示します。つまり、画像アップロード経由の格納型クロスサイトスクリプティングです。ファイルを受け付けること自体は問題ありませんが、HTML として配信し返すのは問題です。
CSV に等号で始まるセルがあるのはなぜですか?
Excel、Google スプレッドシート、LibreOffice は、=、+、-、@ で始まるセルを数式として解釈するからです。アプリケーションがユーザーの入力したテキストを、これらの先頭文字をエスケープせずに CSV に書き出すと、ユーザーがフォームに入力した内容が同僚のスプレッドシートで有効な数式として開かれてしまいます。対策は、書き出し時にそうしたセルの先頭にアポストロフィを付けるか、引用符で囲むことです。
写真には本当に GPS 座標が入っていますか?
はい。トロントの CN タワー(北緯 43.6426 度、西経 79.3871 度)の座標と高度が入っています。さらに Orientation 6 も設定されており、ビューアーは正しい向きで表示するために時計回りに 90 度回転させる必要があります。この 2 つで、あらゆる画像処理パイプラインが正しく扱うべき 2 点――公開前に位置情報を削除すること、縦向きの写真が横倒しにならないよう回転情報を反映すること――を確認できます。
自動テストスイートで使えますか?
はい、まさにそのためのファイルです。どのファイルも内容が固定されており、SHA-256 をここで公開しています。直リンクには長いキャッシュ有効期間と CORS を許可するヘッダーが付いています。テストでハッシュを固定しておけば、フィクスチャが変わったときにすぐ気づけます。
不具合や改善できそうな点を見つけましたか?いただいたメッセージはすべて読み、すぐに対応します。
正常なファイルが必要ですか?
ほとんどのテストで必要なのは正常に使えるファイルです。そちらも公開しています。本物の画像、動画、音声、文書、アーカイブ、データ、フォント、3D モデルを、正確なサイズとハッシュ付きで用意しています。