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 shape | stack 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 (expression → logical_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.