-
Notifications
You must be signed in to change notification settings - Fork 601
Avoid stack overflows via configurable with_recursion_limit
#764
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
Conversation
@@ -55,6 +56,92 @@ macro_rules! return_ok_if_some { | |||
}}; | |||
} | |||
|
|||
#[cfg(feature = "std")] | |||
/// Implemenation [`RecursionCounter`] if std is available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the key change for actually limiting recursion depth
/// each call to `try_decrease()`, when it reaches 0 an error will | ||
/// be returned. | ||
/// | ||
/// Note: Uses an Rc and AtomicUsize in order to satisfy the Rust |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Rc approach is from @46bit -- if anyone has ideas about how to avoid it, I would love a PR to help.
} | ||
} | ||
|
||
/// Guard that increass the remaining depth by 1 on drop |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DepthGuard
is used to automatically ensure the recursion depth is restored upon function return
/// # Ok(()) | ||
/// # } | ||
/// ``` | ||
pub fn new(dialect: &'a dyn Dialect) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the signature here has changed - I tried to illustrate the intended usage with doc comments
} | ||
|
||
/// Parse a SQL statement and produce an Abstract Syntax Tree (AST) | ||
pub fn parse_sql(dialect: &dyn Dialect, sql: &str) -> Result<Vec<Statement>, ParserError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
github mangles the diff -- this function still exists with the same signature. It now also has docstrings
/// # Ok(()) | ||
/// # } | ||
/// ``` | ||
pub fn parse_statements(&mut self) -> Result<Vec<Statement>, ParserError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was factored out of parse_sql
so that people directly using Parser::new()
could also have access to that logic
Pull Request Test Coverage Report for Build 3698164587
💛 - Coveralls |
cc @AugustoFKL @andygrove and @Dandandan |
with_recursion_limit
configurable recursion limit to parserwith_recursion_limit
Closes #305. Alternative to #751
This PR is based off the approach from @46bit in #501 and includes some code and tests from there. While it may look like a large change, it is mostly docstring changes and tests. The code changes are very small
Rationale
Given a deeply nested input,
sqlparser
will overflow the stack, resulting in a panic/segfault.Changes
parse_expr
,parse_statement
andparse_query
API Changes
The
Parser::new()
signature is change, but it is now documented. All other changes are to unreleased code added in #710 by @ankrgylNotes
The only recursive nested structures are
Expr
,Statement
, andQuery
(as they are the places that areBox
ed in the AST). Thus it is sufficient to check recursion depth at each of these points