Skip to content

fix(ole): repair the zero-filled MiniFAT Apple's Cocoa exporter emits - #42

Open
mathurshubham wants to merge 1 commit into
firecrawl:mainfrom
mathurshubham:fix/repair-zeroed-minifat
Open

fix(ole): repair the zero-filled MiniFAT Apple's Cocoa exporter emits#42
mathurshubham wants to merge 1 commit into
firecrawl:mainfrom
mathurshubham:fix/repair-zeroed-minifat

Conversation

@mathurshubham

@mathurshubham mathurshubham commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #37.

Diagnosis

Dissected the reporter's file (and a locally generated textutil -convert doc twin): Apple's Cocoa exporter zero-fills the MiniFAT sector instead
of writing FREESECT/ENDOFCHAIN markers
. Every entry then reads as
"next is mini sector 0", which is the doubly-linked chain cfb rejects
("mini sector 0 pointed to twice") before any content is visible.

MiniFAT entries: [0, 0, 0, 0, ...]           ← all 128 entries
dir: WordDocument       start=0  size=4096   ← regular sectors
     1Table             start=8  size=4096   ← regular sectors
     \x05SummaryInformation start=16 size=4096 ← regular sectors

Everything the .doc parser needs lives in regular sectors — the file is
fully convertible; only the container refuses to open.

The fix

A repair pass in shared/binary.rs, used by every OLE2 open site (doc, ppt,
and byte-content detection): when cfb refuses the file, check for the
defect's exact signature and rebuild the MiniFAT from the directory entries,
then retry the open once.

Safety is the design center — an all-zero MiniFAT is impossible in a
valid file (entry 0 would point at itself), so the repair can never fire on
a well-formed one. It is further gated on:

  • CFB magic and a sane sector shift;
  • no external DIFAT chain (writers with this defect never need one);
  • every MiniFAT entry zero — one nonzero entry and the original error
    surfaces unchanged;
  • no overlapping rebuilt chains (each mini stream below the cutoff owns
    ceil(size / 64) contiguous sectors from its start, which is how
    sequential writers allocate them) — ambiguity aborts the repair.

Version-3 (512-byte) and version-4 (4096-byte sector) containers both
handled — sector N lives at (N + 1) << sector_shift.

Verification

  • The issue's repro (textutil -stdin -convert doc on macOS 26) converts:
    Alpha paragraph. / Beta paragraph. — and a second, larger TextEdit file
    as well. Detection from bytes now also identifies these as .doc.
  • New fixture malformed/zeroed-minifat--recovers.doc — the committed
    LibreOffice text.doc with its MiniFAT zeroed by the generator (pure
    byte mutation, no macOS needed in CI). Its snapshot is byte-identical
    to the pristine text.doc snapshot
    , proving full recovery.
  • Unit tests: zeroed MiniFAT repaired with all stream bytes intact
    (mini-stream and regular alike, v4 container from cfb::create); valid
    files bypass the repair; non-zero MiniFAT corruption keeps its original
    error; non-OLE bytes fail cleanly.
  • cargo fmt --check, clippy --workspace --all-targets --all-features -D warnings, cargo test --locked all green; the only snapshot in the
    diff is the new fixture's.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

.doc files written by TextEdit ("Save as Word 97") and `textutil
-convert doc` zero-fill the MiniFAT instead of terminating chains with
FREESECT/ENDOFCHAIN, so every entry reads as "next is mini sector 0"
and cfb rejects the file ("Malformed MiniFAT: mini sector 0 pointed to
twice") before any content is seen.

An all-zero MiniFAT cannot occur in a valid file - entry 0 would point
at itself - so that exact shape is safe to treat as the writer defect:
rebuild the chains from the directory entries (each mini stream below
the cutoff owns contiguous sectors from its start, sized from the entry)
and retry the open. The repair is gated on the full signature - CFB
magic, no external DIFAT, every MiniFAT entry zero, no overlapping
rebuilt chains - and any other failure keeps its original error.

doc, ppt, and content detection all open through the new helper, so a
TextEdit .doc is both detected from bytes and converted. The streams
the parsers need live in regular sectors; the repair only has to make
the container open.

Fixes firecrawl#37
@daljeetkaurdaljeetpadda-ui

Copy link
Copy Markdown

hi i would like to work on this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

doc: Apple textutil-authored .doc is rejected at open — cfb reports "Malformed MiniFAT (mini sector 0 pointed to twice)"

2 participants