Skip to main content

Limits

Struct Limits 

Source
pub struct Limits {
Show 18 fields pub max_object_nesting: u32, pub max_array_len: usize, pub max_xref_size: u32, pub max_object_number: u32, pub header_scan: u64, pub startxref_scan: u64, pub max_word_len: usize, pub max_page_tree_depth: u32, pub max_page_count: u32, pub max_decoded_stream_len: usize, pub max_cmap_ranges: usize, pub max_name_tree_depth: u32, pub max_script_loop_iterations: u64, pub max_script_recursion: usize, pub max_script_stack: usize, pub max_calculate_depth: u32, pub max_render_pixels: Option<u64>, pub deadline: Option<Deadline>,
}
Expand description

Caps applied while reading a document. Plain configuration data: pass it down, never store it in a parser struct that also owns state.

Which operations honour which cap: the parser’s caps (nesting, array length, xref size, object numbers, the scans, word length, the page tree, stream length) are read while opening and while fetching objects; the CMap and name-tree caps while loading fonts and document-level trees; the script budgets by the script engine alone. Limits::max_render_pixels is read by the facade’s render entry points, before a target is allocated. Limits::deadline is read at every boundary listed on that field.

use pdfrum_common::Limits;

// PDFium-equivalent defaults, with one cap tightened for a fuzz budget.
let limits = Limits { max_array_len: 1 << 20, ..Limits::default() };
assert_eq!(limits.max_object_nesting, 64);
assert_eq!(limits.max_object_number, 25_165_824);

Fields§

§max_object_nesting: u32

Maximum depth of nested arrays/dictionaries accepted while parsing an object body. Enforced at parse time so access code may recurse freely.

§max_array_len: usize

Maximum number of elements in one array. PDFium has no such cap; ours is consulted by the object parser (pdfrum_parser::syntax), the ToUnicode CMap reader and the Type 1 charstring decoder.

§max_xref_size: u32

Maximum number of entries a cross-reference section may declare; one past the largest legal object number.

§max_object_number: u32

Largest legal object number. PDFium: kMaxObjectNumber (24·2²⁰).

§header_scan: u64

How far from the start of the file the %PDF- header is searched for.

§startxref_scan: u64

How far back from the end of the file startxref is searched for.

§max_word_len: usize

Maximum number of bytes kept from one syntax token (names, keywords). Longer tokens are truncated, matching PDFium’s word buffer.

§max_page_tree_depth: u32

Maximum depth of the page tree walk before it gives up.

§max_page_count: u32

Maximum number of pages a document may report.

§max_decoded_stream_len: usize

Maximum number of bytes any single stream filter may produce.

PDFium has no cap here: Flate and LZW decode until they stop, and only the size it reports saturates, at kMaxTotalOutSize = 1 GiB (flatemodule.cpp), silently truncating anything larger. We decline to inherit that zip-bomb surface and turn the same ceiling into a hard rejection instead; past 1 GiB the oracle’s reported size has already stopped tracking its content, so no stream that decodes faithfully in the C++ changes behavior. RunLengthDecode keeps its own, much smaller and behaviorally load-bearing 20 MiB cap in pdfrum-filters.

§max_cmap_ranges: usize

Maximum number of codespace ranges, and separately of wide-code CID ranges, one embedded CMap program may declare.

PDFium has no cap: both lists grow with the program. The default here is one range per possible two-byte code, which no real CMap approaches and which bounds a hostile program’s memory at a few megabytes; past it further ranges are dropped with a diagnostic rather than erroring, in the same spirit as max_decoded_stream_len.

§max_name_tree_depth: u32

Maximum depth of a name tree, number tree, structure tree, form-field /Parent walk, field-name trie, or chained /Next action.

PDFium caps four of those six at 32 and leaves the number tree and the action chain uncapped — both of which are unbounded recursion on a cyclic file. One knob covers all six; no real document approaches it, and exceeding it answers “not found” with a diagnostic rather than erroring.

§max_script_loop_iterations: u64

How many loop iterations one script may run before it is stopped.

Roughly ten seconds of the tightest possible loop. No real form script iterates a thousand times; the number is a ceiling on a hostile file, not a budget a legitimate one has to fit inside. Exhausting it is a Diagnostic and the refusing answer from the hook that was running — never a hang, never a panic, and never a silent acceptance.

PDFium has no equivalent at all: while(true){} under V8 runs until the process is killed from outside.

§max_script_recursion: usize

How deep one script may recurse. boa’s own default.

§max_script_stack: usize

How large one script’s value stack may grow. boa’s own default.

§max_calculate_depth: u32

How deep a calculation may trigger another calculation.

One, because a calculation that runs during another calculation is refused rather than counted down: the outer sweep is authoritative and every nested call returns immediately. The field makes that depth configurable rather than looser.

§max_render_pixels: Option<u64>

The most pixels one render may produce: width × height of the target under the render transform. None — the default — is no cap.

PDFium has none: pdfium_test --scale sizes the bitmap and only CFX_DIBitmap’s pitch overflow refuses it. Read by the facade before the target is allocated, so a request above the cap costs nothing; exceeding it is LimitExceeded::RenderPixels.

§deadline: Option<Deadline>

When every operation on the document must have stopped. None — the default — is no limit.

A Deadline is a stop flag any thread raises (Deadline::manual and Deadline::stop, the mechanism every target has) and, on targets with a clock, a budget that raises it for you (Deadline::after). A host on wasm32 has only the flag, and its own timer.

Honoured cooperatively, at the boundaries the engine already has: opening (once on entry, then every 4096 tokens of a cross-reference rebuild scan), loading a page, interpreting a content stream (every 256 operators), rasterizing (every object), extracting a page’s text (on entry), and running a script (on entry). The fallible entries — open, page load, render — answer LimitExceeded::Time for a spent budget and LimitExceeded::Stopped for a raised flag; the infallible ones — the interpreter, the extractor — stop where they are, record DiagKind::TimeLimitReached and return what they have; a script refuses as an exhausted script budget does. PDFium has no equivalent: a host wraps the process in a timer.

Implementations§

Source§

impl Limits

Source

pub fn check_deadline(&self, during: Operation) -> Result<(), LimitExceeded>

Ok unless a deadline is set and has passed — the one call every cooperative boundary makes. Costs one branch without a deadline.

§Errors

LimitExceeded::Time once the deadline has passed.

Trait Implementations§

Source§

impl Clone for Limits

Source§

fn clone(&self) -> Limits

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Limits

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Limits

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for Limits

Source§

impl PartialEq for Limits

Source§

fn eq(&self, other: &Limits) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Limits

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.