Skip to content

fix: enforce expression size limit before source construction#1302

Open
thesmartshadow wants to merge 1 commit intogoogle:masterfrom
thesmartshadow:fix/early-expression-size-limit-enforcement
Open

fix: enforce expression size limit before source construction#1302
thesmartshadow wants to merge 1 commit intogoogle:masterfrom
thesmartshadow:fix/early-expression-size-limit-enforcement

Conversation

@thesmartshadow
Copy link
Copy Markdown

This PR enforces the configured ParserExpressionSizeLimit in Env.Compile()
and Env.Parse() before calling common.NewTextSource(), preventing memory
allocation proportional to the full input size for oversized expressions.

Problem

The current flow is:

  1. Env.Compile(txt)common.NewTextSource(txt)
  2. common.NewTextSource()runes.NewBufferAndLineOffsets(contents)
  3. runes.newBuffer() eagerly allocates capacity proportional to the full input
  4. Only afterwards does the parser check buf.Len() > p.expressionSizeCodePointLimit

Applications configuring ParserExpressionSizeLimit(1000) expect oversized
expressions to be rejected cheaply, but the internal source/rune-buffer
materialization still occurs before enforcement.

Fix

Add an early utf8.RuneCountInString(txt) check in both Compile() and
Parse() before calling common.NewTextSource().

Before / After

  • Before: 100MB compile → ~95MiB → 191MiB (returns size-limit error)
  • After: 100MB compile → ~95MiB → 95MiB (same error, no memory spike)

The test TestExpressionSizeLimitEarlyEnforcement confirms 0MiB allocation
delta for a 10MB oversized expression with a 1000 code point limit.

Enforce the configured ParserExpressionSizeLimit in Env.Compile() and
Env.Parse() before calling common.NewTextSource(), preventing memory
allocation proportional to the full input size for oversized expressions.

Previously, oversized expressions were correctly rejected but only after
the internal rune buffer had already been allocated. This allowed
substantial memory allocation even when a strict size limit was configured.

The fix adds an early utf8.RuneCountInString() check which is O(n) in CPU
but avoids the additional memory allocation and GC pressure caused by
eager source/rune-buffer construction.

CWE-400: Uncontrolled Resource Consumption
@thesmartshadow thesmartshadow force-pushed the fix/early-expression-size-limit-enforcement branch from 985387a to 9b5a353 Compare April 11, 2026 20:02
@TristonianJones TristonianJones requested a review from jcking April 12, 2026 22:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant