Forráskód Böngészése

LibSQL: Limit the allowed depth of an expression tree

According to the definition at https://sqlite.org/lang_expr.html, SQL
expressions could be infinitely deep. For practicality, SQLite enforces
a maxiumum expression tree depth of 1000. Apply the same limit in
LibSQL to avoid stack overflow in the expression parser.

Fixes https://crbug.com/oss-fuzz/34859.
Timothy Flynn 4 éve
szülő
commit
f8f36effc9

+ 7 - 0
Tests/LibSQL/TestSqlExpressionParser.cpp

@@ -602,3 +602,10 @@ TEST_CASE(in_selection_expression)
     validate("15 IN (SELECT * FROM table)", false);
     validate("15 NOT IN (SELECT * FROM table)", true);
 }
+
+TEST_CASE(stack_limit)
+{
+    auto too_deep_expression = String::formatted("{:+^{}}1", "", SQL::Limits::maximum_expression_tree_depth);
+    EXPECT(!parse(too_deep_expression.substring_view(1)).is_error());
+    EXPECT(parse(too_deep_expression).is_error());
+}

+ 6 - 0
Userland/Libraries/LibSQL/Parser.cpp

@@ -352,6 +352,11 @@ RefPtr<CommonTableExpressionList> Parser::parse_common_table_expression_list()
 
 NonnullRefPtr<Expression> Parser::parse_expression()
 {
+    if (++m_parser_state.m_current_expression_depth > Limits::maximum_expression_tree_depth) {
+        syntax_error(String::formatted("Exceeded maximum expression tree depth of {}", Limits::maximum_expression_tree_depth));
+        return create_ast_node<ErrorExpression>();
+    }
+
     // https://sqlite.org/lang_expr.html
     auto expression = parse_primary_expression();
 
@@ -362,6 +367,7 @@ NonnullRefPtr<Expression> Parser::parse_expression()
     // FIXME: Parse 'function-name'.
     // FIXME: Parse 'raise-function'.
 
+    --m_parser_state.m_current_expression_depth;
     return expression;
 }
 

+ 6 - 0
Userland/Libraries/LibSQL/Parser.h

@@ -14,6 +14,11 @@
 
 namespace SQL {
 
+namespace Limits {
+// https://www.sqlite.org/limits.html
+constexpr size_t maximum_expression_tree_depth = 1000;
+}
+
 class Parser {
     struct Position {
         size_t line { 0 };
@@ -48,6 +53,7 @@ private:
         Lexer m_lexer;
         Token m_token;
         Vector<Error> m_errors;
+        size_t m_current_expression_depth { 0 };
     };
 
     NonnullRefPtr<Statement> parse_statement();