From b36dafc819fbc873d821b4aa88d56a34d30ebea3 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Thu, 31 Jul 2025 11:38:14 -0400 Subject: [PATCH] Improve regex --- superset/sql_parse.py | 10 +++++++--- tests/unit_tests/sql_parse_tests.py | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/superset/sql_parse.py b/superset/sql_parse.py index 6c62872af47..678c3a8101e 100644 --- a/superset/sql_parse.py +++ b/superset/sql_parse.py @@ -88,9 +88,13 @@ logger = logging.getLogger(__name__) # reference: https://sqlparse.readthedocs.io/en/stable/extending/ lex = Lexer.get_default_instance() sqlparser_sql_regex = keywords.SQL_REGEX -sqlparser_sql_regex.insert( - 25, (r"'(?:[^'\\]|\\\\?|'')*'", sqlparse.tokens.String.Single) -) +# Replace the string pattern at position 25 to fix ReDOS vulnerability +# Use two patterns: first for strings ending with backslash, then for general escaped +# strings +# Pattern 1: Match strings that end with a single backslash (like '\') +sqlparser_sql_regex[25] = (r"'[^'\\]*\\'(?!\w)", sqlparse.tokens.String.Single) +# Pattern 2: Match general strings with escape sequences +sqlparser_sql_regex.insert(26, (r"'(?:[^'\\]|\\.|'')*'", sqlparse.tokens.String.Single)) lex.set_SQL_REGEX(sqlparser_sql_regex) diff --git a/tests/unit_tests/sql_parse_tests.py b/tests/unit_tests/sql_parse_tests.py index 23aa6b0b125..5de9d9d87fd 100644 --- a/tests/unit_tests/sql_parse_tests.py +++ b/tests/unit_tests/sql_parse_tests.py @@ -1309,9 +1309,13 @@ def test_sanitize_clause_multiple(): def test_sqlparse_issue_652(): + stmt = sqlparse.parse(r"SELECT 'Don\'t stop' FROM table")[0] + assert len(stmt.tokens) == 7 + assert str(stmt.tokens[2]) == r"'Don\'t stop'" + stmt = sqlparse.parse(r"foo = '\' AND bar = 'baz'")[0] assert len(stmt.tokens) == 5 - assert str(stmt.tokens[0]) == "foo = '\\'" + assert str(stmt.tokens[0]) == r"foo = '\'" @pytest.mark.parametrize(