RUSTSEC-2026-0436 json
Panic and unbounded allocation (OOM) in the CFB/OLE2 parser on malformed input
published 2026-10-28 11 d ago modified 2026-11-03 5 d ago
- cvss
- 7.5
- version 3.1, OSV
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
The Compound File Binary (OLE2) parser (`src/cfb.rs`), used when reading `.xls` and `.xlsb` workbooks and when extracting VBA projects from `.xlsx`, can panic or allocate without bound on crafted input. Both are reachable through the public reader API (`open_workbook`, `Xls::new`, `Xlsb::new`) on an attacker-supplied file. Impact is denial of service only — no memory unsafety (safe Rust turns the out-of-bounds read into a bounds-checked panic).
1. **Reachable panic (out-of-bounds slice index).** The directory stream is iterated with `.chunks(128)`, but `Directory::from_slice` reads fixed offsets (`buf[..64]`, `buf[116..120]`, `buf[120..128]`) without checking the chunk length. A directory stream whose length is not a multiple of 128 yields a short final chunk, causing a panic (`range end index 64 out of range for slice of length N`). `SectorSize::Small` 64-byte mini sectors are a second trigger.
2. **Unbounded allocation / OOM.** The DIFAT loader grows the `difat` vector without bounding the number of iterations; a crafted self-referential DIFAT chain drives a multi-gigabyte allocation from a tiny file (a 512-byte file attempts an allocation of several gigabytes).
A consumer that parses untrusted or user-supplied spreadsheets can be crashed (thread panic, or process abort under `panic=abort`) or driven out of memory by a small crafted file.
Fixed in calamine 0.38.0 (commit [b8ec4f0](https://github.com/tafia/calamine/commit/b8ec4f0)); the maintainer confirmed the fix in https://github.com/tafia/calamine/pull/762.
Patch / fix
CVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| OSV | 3.1 | 7.5 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| crates.io | calamine | >=0.0.0-0, <0.38.0 |
0.38.0 |
References
Sources
Fencer Vulns keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.