This is an automated email from the ASF dual-hosted git repository. github-bot pushed a commit to branch gh-readonly-queue/main/pr-2282-1097a0d5a6a852737b55f96bd38fba3f2ece9bd0 in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit 7c4eac3098063d191337ecb9ac0f695ac205de67 Author: Dmitrii Blaginin <[email protected]> AuthorDate: Tue Mar 24 04:39:25 2026 +0000 recursive protection for `parse_subexpr` (#2282) --- src/parser/mod.rs | 1 + tests/sqlparser_common.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/parser/mod.rs b/src/parser/mod.rs index cefc0c6f..3a970f7a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1386,6 +1386,7 @@ impl<'a> Parser<'a> { } /// Parse tokens until the precedence changes. + #[cfg_attr(feature = "recursive-protection", recursive::recursive)] pub fn parse_subexpr(&mut self, precedence: u8) -> Result<Expr, ParserError> { let _guard = self.recursion_counter.try_decrease()?; debug!("parsing expr"); diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 6f9e4695..cff29bfe 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -15687,6 +15687,34 @@ fn overflow() { let statement = statements.pop().unwrap(); assert_eq!(statement.to_string(), sql); } + +#[test] +fn parse_deeply_nested_boolean_expr_does_not_stackoverflow() { + fn build_nested_expr(depth: usize) -> String { + if depth == 0 { + return "x = 1".to_string(); + } + format!( + "({} OR {} AND ({}))", + build_nested_expr(0), + build_nested_expr(0), + build_nested_expr(depth - 1) + ) + } + + let depth = 200; + let where_clause = build_nested_expr(depth); + let sql = format!("SELECT pk FROM tab0 WHERE {where_clause}"); + + let mut statements = Parser::new(&GenericDialect {}) + .try_with_sql(&sql) + .expect("tokenize to work") + .with_recursion_limit(depth * 10) + .parse_statements() + .unwrap(); + let statement = statements.pop().unwrap(); + assert_eq!(statement.to_string(), sql); +} #[test] fn parse_select_without_projection() { let dialects = all_dialects_where(|d| d.supports_empty_projections()); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
