Skip to content

Commit e504e65

Browse files
authored
Add advisory for lopdf: stack overflow via deeply nested PDF objects (#2984)
1 parent 49f5431 commit e504e65

1 file changed

Lines changed: 36 additions & 0 deletions

File tree

crates/lopdf/RUSTSEC-0000-0000.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
```toml
2+
[advisory]
3+
id = "RUSTSEC-0000-0000"
4+
package = "lopdf"
5+
date = "2026-06-21"
6+
categories = ["denial-of-service"]
7+
keywords = ["dos", "stack-overflow", "recursion", "untrusted-input", "pdf"]
8+
cvss = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
9+
references = ["https://github.com/J-F-Liu/lopdf/issues/502", "https://github.com/J-F-Liu/lopdf/pull/503", "https://github.com/J-F-Liu/lopdf/commit/c755394"]
10+
11+
[versions]
12+
patched = [">= 0.42.0"]
13+
```
14+
15+
# Stack overflow in lopdf via deeply nested PDF objects
16+
17+
`lopdf::Document::load_mem` (and the other `load*` entry points) parses nested PDF arrays and dictionaries with unbounded recursion. A small crafted PDF whose Catalog contains a deeply nested array (`/X [[[ … ]]]`, on the order of 10,000 levels) exhausts the call stack and aborts the process with `SIGABRT`.
18+
19+
Because this is a stack-overflow abort rather than a `panic!`, it cannot be caught with `catch_unwind`: any service that parses untrusted PDF input with lopdf can be crashed by a ~21 KB file, resulting in a denial of service.
20+
21+
Confirmed on lopdf 0.41.0 and earlier; fixed in 0.42.0. Default configuration, no features changed.
22+
23+
## Proof of concept
24+
25+
```rust
26+
fn main() {
27+
let bytes = std::fs::read("poc.pdf").unwrap(); // ~10,380-deep nested array in the Catalog
28+
let _ = lopdf::Document::load_mem(&bytes); // stack overflow -> SIGABRT
29+
}
30+
```
31+
32+
An equivalent PoC is a minimal PDF whose Catalog `/X` value is `"[" * 10380 + "]" * 10380`.
33+
34+
## Suggested fix
35+
36+
Enforce a maximum object-nesting depth in the parser and return an `Err` instead of recursing without bound.

0 commit comments

Comments
 (0)