Repair benchmark
A fixed, downloadable corpus of corrupted files. Our engine's results on every one of them, published with the method — including the ones it fails.
“Opens” is the strictest cell we could define: the output must decode completely, as its original format, with a stock third-party decoder — not with our own validator. The corpus is synthetic and regenerable from a seed, so anyone can reproduce this table or run another tool against the same bytes.
Results
Format × corruption. Hover a cell for the engine's own notes.
| Format | Truncated at 60% | Header zeroed (64 B) | Garbage prefix (4 KiB) | Mid-file zeroed (4 KiB) | Wrong extension | Opens |
|---|---|---|---|---|---|---|
| JPEG | StructuralOpens6 ms | FailedDoes not open1 ms | ExtractedOpens4 ms | CleanOpens1 ms | CleanOpens0 ms | 4 / 5 |
| PNG | FailedDoes not open2 ms | FailedDoes not open3 ms | StructuralOpens2 ms | ExtractedDoes not open4 ms | CleanOpens0 ms | 2 / 5 |
| GIF | StructuralOpens1 ms | FailedDoes not open0 ms | StructuralOpens0 ms | StructuralOpens0 ms | CleanOpens0 ms | 4 / 5 |
| MP4 | StructuralOpens0 ms | FailedDoes not open1 ms | ExtractedOpens2 ms | CleanOpens0 ms | CleanOpens0 ms | 4 / 5 |
StructuralOpens2 ms | StructuralOpens4 ms | CleanOpens1 ms | ExtractedOpens3 ms | CleanOpens1 ms | 5 / 5 | |
| DOCX | StructuralOpens0 ms | StructuralOpens0 ms | CleanOpens0 ms | ExtractedDoes not open1 ms | CleanOpens0 ms | 4 / 5 |
| Opens | 5 / 6 | 2 / 6 | 6 / 6 | 4 / 6 | 6 / 6 | 23 / 30 |
- Clean
- The engine judged the input already valid and left it alone.
- Structural
- Tier 1 — a format plugin rewrote the file structure in place.
- Extracted
- Tier 2/3 — valid file(s) were carved out of the damaged container.
- Salvage
- Tier 4 — only clearly-labelled, low-confidence salvage artifacts (e.g. extracted text).
- Failed
- No tier produced any output.
Same corpus, other tools
Files opened out of 5 per format, under the identical rule. We publish a competitor number only after running that tool by hand against the downloadable corpus; until then the cell says so.
| Format | DataRecover Pro | untruncMP4/MOV only | Stellar Repair for Videovideo only | Disk Drillrecovery suite |
|---|---|---|---|---|
| JPEG | 4 / 5 | not yet measured | not yet measured | not yet measured |
| PNG | 2 / 5 | not yet measured | not yet measured | not yet measured |
| GIF | 4 / 5 | not yet measured | not yet measured | not yet measured |
| MP4 | 4 / 5 | not yet measured | not yet measured | not yet measured |
| 5 / 5 | not yet measured | not yet measured | not yet measured | |
| DOCX | 4 / 5 | not yet measured | not yet measured | not yet measured |
Methodology
Corpus generation
Six clean sources are synthesized in code from a fixed seed (0x5eedda7a20260911): JPEG, PNG and GIF are rendered images; the MP4 is a complete ISOBMFF container with real sample tables and 60 length-prefixed samples; the PDF is 24 pages with a correct xref; the DOCX has the standard OOXML parts plus an embedded PNG. Each source is put through the five corruption operators below, giving 30 files. Re-running the generator reproduces the same bytes and SHA-256s — they are listed in manifest.json.
Run environment
- Engine
- v1.2.4 (e43f239)
- Date
- 2026-09-12T05:12:24Z
- Machine
- Apple M5 Max · macos/aarch64
- Build
- release, single run
Corruption types
Truncated at 60%
The file is cut at 60% of its length. The tail — and for some formats the index that lives there — is gone for good.
Header zeroed (64 B)
The first 64 bytes are overwritten with zeros, destroying the magic number and the start of the header.
Garbage prefix (4 KiB)
4 KiB of seeded random bytes are prepended; every byte of the original file is still present, just not at offset 0.
Mid-file zeroed (4 KiB)
A 4 KiB block centred on the midpoint is overwritten with zeros — the classic bad-sector pattern.
Wrong extension
The bytes are untouched but the file carries the wrong extension, so extension-based tools pick the wrong decoder.
How results are judged
- Corpus: 6 synthetic clean sources (JPEG/PNG/GIF rendered with the `image` crate; MP4, PDF and DOCX built in code) x 5 corruption operators = 30 files, generated from a fixed seed. Re-running `gen` reproduces the same bytes and sha256s.
- Engine path: `RepairEngine::repair_file` — the same tiered cascade (Tier 1 plugin repair, Tier 2 deep scan, Tier 3 extraction, Tier 4 salvage) the desktop app calls through the privileged service. Tier 1 plugins run in-process here; the app additionally wraps single-plugin repairs in a sandboxed worker, which changes isolation, not output.
- Assessment: `RepairEngine::assess` on the bytes, routed by the file's on-disk extension (the same routing the app uses); the dedicated format plugin's verdict takes precedence over extraction-only plugins.
- Tier reported: clean = engine judged input already valid; structural = Tier 1 rewrote the file; partial = Tier 2/3 carved valid file(s) out; salvage = only labelled low-confidence salvage artifacts; failed = nothing produced.
- "Opens" = the primary output decodes as the ORIGINAL format with an independent stock decoder: jpeg-decoder (strict), the png/gif crates, lopdf (all pages' content streams readable), the zip crate (every member inflates with a valid CRC, mandatory OOXML parts present) and an in-house ISOBMFF box walk (boxes tile the file, ftyp first, moov+mdat present, all chunk offsets in-file). Any decoder error counts as "does not open".
- Duration = wall-clock for assess + repair_file on one file, single run, release build, no warm-up. Treat it as an order of magnitude, not a measurement.
- Expected-outcome class describes the theoretical ceiling for the corruption (bytes intact / header rebuild / partial content), not a prediction of any tool's result.
What this does not show
- It is a synthetic corpus. Real camera and phone failures — a GoPro that lost power mid-recording, an iPhone HEVC file with a missing moov, a DSLR card with interleaved fragments — are messier than five clean operators. Good numbers here are necessary, not sufficient.
- “Opens” is not “looks right.” A JPEG or MP4 with 4 KiB zeroed in the middle of its payload can decode without a single error and still show a band of garbage. Those files are marked Clean because no decoder can tell the difference — and neither can we.
- The failures are real. GIF and header-destroyed images are weak spots in this engine version, and the table says so. We would rather publish a gap than a cherry-picked corpus.
- Competitor columns are pending. We have not yet run untrunc, Stellar Repair for Video or Disk Drill against this corpus. Nothing in those columns is estimated or inferred.
- Timings are indicative only. Single run, no warm-up, small files. They tell you the repair is fast, not how fast.
Reproduce it
The corpus is published at /benchmark/corpus.zip (about 2 MB: 6 clean sources, 30 corrupted files, and the manifest with every SHA-256). Point any repair tool at the corrupt/ folder and count what opens under the same rule.
# regenerate the corpus (byte-identical) and run the engine cargo run --release -p datarecover-pro-bench -- gen bench/corpus cargo run --release -p datarecover-pro-bench -- run bench/corpus --out bench/results.json
Try it on your own files.
Scan and preview for free. Repair runs locally, in a sandbox, and you see what opens before you pay.