CVE-2023-30608: Inefficient Regular Expression Complexity (CWE-1333)
value: sqlparse is a non-validating SQL parser module for Python. In affected versions the SQL parser contains a regular expression that is vulnerable to ReDoS (Regular Expression Denial of Service). This issue was introduced by commit `e75e358`. The vulnerability may lead to Denial of Service (DoS). This issues has been fixed in sqlparse 0.4.4 by commit `c457abd5f`. Users are advised to upgrade. There are no known workarounds for this issue.

CWE description: The product uses a regular expression with an inefficient, possibly exponential worst-case computational complexity that consumes excessive CPU cycles.
CVSS v3 base score: 7.5
Published: 2023-04-18T22:15Z
Repository: https://github.com/andialbrecht/sqlparse
Language: Python
Files changed: sqlparse/lexer.py, tests/test_split.py
Commit date: 2015-02-26 12:32:46 -0800
Commit message: Recognize escaped backslashes within strings

Previously if a single quoted string ended with an escaped backslash,
parsing would not consider the string to be terminated.

Diff: diff --git a/sqlparse/lexer.py b/sqlparse/lexer.py
index 3e9a1a6..5282ad3 100644
--- a/sqlparse/lexer.py
+++ b/sqlparse/lexer.py
@@ -189,12 +189,11 @@ class Lexer(object):
             (r'[^\W\d_]\w*(?=[.(])', tokens.Name),  # see issue39
             (r'[-]?0x[0-9a-fA-F]+', tokens.Number.Hexadecimal),
             (r'[-]?[0-9]*(\.[0-9]+)?[eE][-]?[0-9]+', tokens.Number.Float),
             (r'[-]?[0-9]*\.[0-9]+', tokens.Number.Float),
             (r'[-]?[0-9]+', tokens.Number.Integer),
-            # TODO: Backslash escapes?
-            (r"'(''|\\'|[^'])*'", tokens.String.Single),
+            (r"'(''|\\\\|\\'|[^'])*'", tokens.String.Single),
             # not a real string literal in ANSI SQL:
             (r'(""|".*?[^\\]")', tokens.String.Symbol),
             (r'(?<=[\w\]])(\[[^\]]*?\])', tokens.Punctuation.ArrayIndex),
             (r'(\[[^\]]+\])', tokens.Name),
             (r'((LEFT\s+|RIGHT\s+|FULL\s+)?(INNER\s+|OUTER\s+|STRAIGHT\s+)?|(CROSS\s+|NATURAL\s+)?)?JOIN\b', tokens.Keyword),
diff --git a/tests/test_split.py b/tests/test_split.py
index e4ebf7e..54e8d04 100644
--- a/tests/test_split.py
+++ b/tests/test_split.py
@@ -20,10 +20,14 @@ class SQLSplitTest(TestCaseBase):
         stmts = sqlparse.parse(''.join([self._sql1, sql2]))
         self.assertEqual(len(stmts), 2)
         self.ndiffAssertEqual(unicode(stmts[0]), self._sql1)
         self.ndiffAssertEqual(unicode(stmts[1]), sql2)
 
+    def test_split_backslash(self):
+        stmts = sqlparse.parse(r"select '\\'; select '\''; select '\\\'';")
+        self.assertEqual(len(stmts), 3)
+
     def test_create_function(self):
         sql = load_file('function.sql')
         stmts = sqlparse.parse(sql)
         self.assertEqual(len(stmts), 1)
         self.ndiffAssertEqual(unicode(stmts[0]), sql)

Vulnerable code:             # TODO: Backslash escapes?
            (r"'(''|\\'|[^'])*'", tokens.String.Single),
Fixed code:             (r"'(''|\\\\|\\'|[^'])*'", tokens.String.Single),
    def test_split_backslash(self):
        stmts = sqlparse.parse(r"select '\\'; select '\''; select '\\\'';")
        self.assertEqual(len(stmts), 3)