Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to specify a parser stack limit #308

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

zsol
Copy link
Contributor

@zsol zsol commented Jun 29, 2022

TODO:

  • documentation
  • change placeholder STACK OVERFLOW expected string to something nicer
  • test failure case: non integer stack limit given

This PR implements a new stack_limit directive in the meta grammar. When specified, the generated parser will keep track of rule invocation depth and error out when the depth is beyond the specified maximum.

I'm not married to any of the naming and syntax here, feel free to suggest better alternatives.

A better way of raising errors from this might be to introduce a new RuleResult variant that immediately terminates parsing instead of carrying on with alternatives. I think that's a great future improvement, but didn't consider for this PR because it would expand the scope quite a bit.

Fixes #282. This PR depends on #307.

@kevinmehall
Copy link
Owner

A better way of raising errors from this might be to introduce a new RuleResult variant that immediately terminates parsing instead of carrying on with alternatives. I think that's a great future improvement, but didn't consider for this PR because it would expand the scope quite a bit.

I don't think it's workable to treat reaching the stack limit as a simple parse failure because it will cause /, &, and ! operators to misbehave when reaching the limit. That's going to end up sometimes resulting in "successful" parses with unexpected parse trees. Possibly could even be weaponized to let an attacker skip parts of a grammar that involve deeper rule nesting, which could bypass data validation and produce a result that shouldn't be allowed.

For example, with the grammar

peg::parser! { grammar test() for str {
    stack_limit 2;

    rule keyword() -> Expr
        = "foo" { Expr::Foo }
        / "bar" { Expr::Bar }

    pub rule expr() -> Expr
        = "(" e: expr() ")" { e }
        / keyword()
        / v:$(['a'..='z']+) { Expr::Variable(v.to_string()) }
}}

the input ((foo)) incorrectly returns Expr::Variable("foo") instead of Expr::Foo because the call to keyword() fails with the stack limit.

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.

Allows to make the parser fail before hitting a stack overflow error
2 participants