Skip to main content

Module expr_depth

Module expr_depth 

Source
Expand description

Nesting-depth limits for the raster-algebra expression front-ends

Both expression front-ends in this crate — the Pest-based crate::dsl parser and the hand-written crate::raster calculator parser — are recursive descent. Without a bound, a deeply nested expression such as ((((((… x …)))))) drives one native stack frame chain per nesting level and aborts the process with a stack overflow. Because a stack overflow is a SIGABRT/SIGSEGV rather than a catchable panic, it cannot be recovered from, so untrusted expression text would be a denial-of-service vector.

The mitigation is a hard, documented depth limit — MAX_EXPRESSION_DEPTH — enforced before any recursion is entered, so over-deep input yields AlgorithmError::NestingTooDeep instead of aborting.

§Choosing the limit

The limit is sized against the most stack-hungry front-end. Measured on aarch64-apple-darwin with the workspace release-ish test profile, by bisecting the nesting depth at which a thread of a given stack size aborts:

Front-end / input shapestack per nesting level
dsl::parse_expression, (x + 1) nesting~12.5 KiB
dsl::parse_expression, if … else if …~12.5 KiB
dsl::parse_expression, ---x unary run~0.8 KiB
RasterCalculator::evaluate, (…) nesting~2.4 KiB
RasterCalculator::evaluate, ---B1 run~0.4 KiB

The DSL figure is dominated by Pest’s generated parser: the expression grammar threads ten rules (expressionlogical_or → … → primary) per nesting level, and each generated rule frame is roughly a kilobyte.

At the worst-case 12.5 KiB per level, MAX_EXPRESSION_DEPTH = 64 costs about 768 KiB of stack — the measured floor below which an expression at exactly the limit stops fitting. That is 37% of the 2 MiB stack Rust gives a non-main thread, the smallest stack any realistic caller (a Rayon worker, a Tokio blocking task, a request handler) will have, leaving ~1.28 MiB for the caller’s own frames. Put the other way: the unguarded DSL parser aborts at depth 165 on a 2 MiB stack, so the limit sits 2.6x below the cliff.

For comparison, real raster algebra is shallow: NDVI (B1 - B2) / (B1 + B2) nests 2 deep, and even elaborate multi-index expressions stay under 10. A limit of 64 is therefore far above any legitimate expression while staying far below the stack budget.

Constants§

MAX_EXPRESSION_DEPTH
Maximum nesting depth accepted by the raster-algebra expression parsers.