blobforge

Adversarial fixtures

break your csv parser

19 CSV files engineered to fail. Each one isolates a single way real CSV breaks real parsers — byte order marks, mixed line endings, unterminated quotes, invalid UTF-8, formula injection — with the correct behaviour documented next to it.

Built in your browser. Nothing is uploaded, and no signup is required.

0Passed
0Failed
19Untested

UTF-8 byte order mark

encoding-bom-utf8.csv

What this tests

The file opens with a UTF-8 BOM (EF BB BF) before the header row.

What a correct parser should do

Strip the BOM before parsing, so the first column is `id` and not `id`. Note that JavaScript's TextDecoder strips it for you — Python's open(encoding='utf-8'), Go, Java and any manual byte split do not. There, every lookup by header name silently returns undefined, and printing the header looks completely normal.

Bytes · 50 B
00000000EFBBBF69642C6E616D652C656D61696C...id,name,email
000000100D0A312C416461204C6F76656C616365..1,Ada Lovelace
000000202C616461406578616D706C652E636F6D,ada@example.com
000000300D0A..
Hover a byte to see why it matters.
  • Byte order mark
  • Carriage return
  • Line feed
  • Delimiter

How to use these fixtures

  1. Download a single file, or take all 19 as a ZIP — the archive includes a README explaining every file.
  2. Run each one through your own CSV import path.
  3. Come back and record whether your parser handled it. Results are kept in your browser, so leaving the page is expected.
  4. Copy the damage report as Markdown and paste it into a pull request or an issue.

Why CSV parsers fail

CSV has no single specification. RFC 4180 describes a common subset, but it is silent on encoding, on line endings other than CRLF, and on what a bare quote inside an unquoted field means. Every parser fills those gaps differently, which is why a file that round-trips cleanly through one tool can silently change when it passes through another.

Most of these failures are silent. A stripped leading zero still looks like a number. A dropped final row still looks like a successful import. That is why each fixture here documents what correct behaviour looks like, rather than only handing you a broken file.

Questions

What makes these different from a normal CSV generator?
Every other generator produces clean, valid data. These files are deliberately hostile — each one isolates a single way real-world CSV breaks real-world parsers, so when your importer fails you know exactly which behaviour is wrong.
Are these files dangerous?
No. They are inert test files for checking your own import pipeline. Nothing here executes on its own — the fixtures that model injection or traversal exist so you can verify your own code rejects them, and the resource-exhaustion ones are deliberately scaled down so they demonstrate the behaviour without taking down the machine you are testing from.
Why does the page show raw bytes?
Because most of these cases are invisible in a text preview. A byte order mark renders as nothing, a bare carriage return looks identical to a CRLF, and a NUL looks like the end of the string. The hex view highlights exactly which bytes matter and explains each one when you hover it.
Does my pass/fail progress get saved?
Yes, in your own browser only, and separately for each format. The workflow expects you to leave the page, run a fixture through your parser, and come back — so results persist locally. Nothing is uploaded, and clearing site data clears them.
Is this free?
Yes. Every fixture is generated in your browser, with no signup and no upload.