This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch 
gh-readonly-queue/main/pr-2199-bc55b379c4faf8c3e175a390ff71c16ca891a0e0
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit e4c550002f6b3d68ed6698e0a8ac6bce633607d6
Author: Luca Cappelletti <[email protected]>
AuthorDate: Fri Feb 6 12:56:29 2026 +0100

    Fixed overflow error, recursion counter was not included for parenthesis 
(#2199)
---
 src/parser/mod.rs            |  3 +++
 tests/sqlparser_common.rs    |  7 +++++++
 tests/sqlparser_snowflake.rs | 10 ++++------
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index fb150b76..14ddd2b5 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -13268,6 +13268,7 @@ impl<'a> Parser<'a> {
     /// preceded with some `WITH` CTE declarations and optionally followed
     /// by `ORDER BY`. Unlike some other parse_... methods, this one doesn't
     /// expect the initial keyword to be already consumed
+    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
     pub fn parse_query(&mut self) -> Result<Box<Query>, ParserError> {
         let _guard = self.recursion_counter.try_decrease()?;
         let with = if self.parse_keyword(Keyword::WITH) {
@@ -15118,7 +15119,9 @@ impl<'a> Parser<'a> {
     }
 
     /// A table name or a parenthesized subquery, followed by optional `[AS] 
alias`
+    #[cfg_attr(feature = "recursive-protection", recursive::recursive)]
     pub fn parse_table_factor(&mut self) -> Result<TableFactor, ParserError> {
+        let _guard = self.recursion_counter.try_decrease()?;
         if self.parse_keyword(Keyword::LATERAL) {
             // LATERAL must always be followed by a subquery or table function.
             if self.consume_token(&Token::LParen) {
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 4f63e4a3..b6b86704 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -11020,6 +11020,13 @@ fn parse_deeply_nested_parens_hits_recursion_limits() {
     assert_eq!(ParserError::RecursionLimitExceeded, res.unwrap_err());
 }
 
+#[test]
+fn parse_update_deeply_nested_parens_hits_recursion_limits() {
+    let sql = format!("\nUPDATE\n\n\n\n\n\n\n\n\n\n{}", "(".repeat(1000));
+    let res = parse_sql_statements(&sql);
+    assert_eq!(ParserError::RecursionLimitExceeded, res.unwrap_err());
+}
+
 #[test]
 fn parse_deeply_nested_unary_op_hits_recursion_limits() {
     let sql = format!("SELECT {}", "+".repeat(1000));
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index cb5af621..014a241f 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -3202,12 +3202,10 @@ fn parse_view_column_descriptions() {
 
 #[test]
 fn test_parentheses_overflow() {
-    // TODO: increase / improve after we fix the recursion limit
-    // for real (see 
https://github.com/apache/datafusion-sqlparser-rs/issues/984)
     let max_nesting_level: usize = 25;
 
-    // Verify the recursion check is not too wasteful... (num of parentheses - 
2 is acceptable)
-    let slack = 2;
+    // Verify the recursion check is not too wasteful (num of parentheses 
within budget)
+    let slack = 3;
     let l_parens = "(".repeat(max_nesting_level - slack);
     let r_parens = ")".repeat(max_nesting_level - slack);
     let sql = format!("SELECT * FROM {l_parens}a.b.c{r_parens}");
@@ -3215,8 +3213,8 @@ fn test_parentheses_overflow() {
         
snowflake_with_recursion_limit(max_nesting_level).parse_sql_statements(sql.as_str());
     assert_eq!(parsed.err(), None);
 
-    // Verify the recursion check triggers... (num of parentheses - 1 is 
acceptable)
-    let slack = 1;
+    // Verify the recursion check triggers (one more paren exceeds the budget)
+    let slack = 2;
     let l_parens = "(".repeat(max_nesting_level - slack);
     let r_parens = ")".repeat(max_nesting_level - slack);
     let sql = format!("SELECT * FROM {l_parens}a.b.c{r_parens}");


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to