1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 12:05:00 +00:00

LibSQL: Parse and execute sequential placeholder values

This partially implements SQLite's bind-parameter expression to support
indicating placeholder values in a SQL statement. For example:

    INSERT INTO table VALUES (42, ?);

In the above statement, the '?' identifier is a placeholder. This will
allow clients to compile statements a single time while running those
statements any number of times with different placeholder values.

Further, this will help mitigate SQL injection attacks.
This commit is contained in:
Timothy Flynn 2022-12-01 22:20:55 -05:00 committed by Andreas Kling
parent 53f8d62ea4
commit b2b9ae27fd
10 changed files with 154 additions and 30 deletions

View file

@ -401,7 +401,6 @@ NonnullRefPtr<Expression> Parser::parse_expression()
if (match_secondary_expression())
expression = parse_secondary_expression(move(expression));
// FIXME: Parse 'bind-parameter'.
// FIXME: Parse 'function-name'.
// FIXME: Parse 'raise-function'.
@ -414,6 +413,9 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
if (auto expression = parse_literal_value_expression())
return expression.release_nonnull();
if (auto expression = parse_bind_parameter_expression())
return expression.release_nonnull();
if (auto expression = parse_column_name_expression())
return expression.release_nonnull();
@ -528,6 +530,21 @@ RefPtr<Expression> Parser::parse_literal_value_expression()
return {};
}
// https://sqlite.org/lang_expr.html#varparam
RefPtr<Expression> Parser::parse_bind_parameter_expression()
{
// FIXME: Support ?NNN, :AAAA, @AAAA, and $AAAA forms.
if (consume_if(TokenType::Placeholder)) {
auto parameter = m_parser_state.m_bound_parameters;
if (++m_parser_state.m_bound_parameters > Limits::maximum_bound_parameters)
syntax_error(DeprecatedString::formatted("Exceeded maximum number of bound parameters {}", Limits::maximum_bound_parameters));
return create_ast_node<Placeholder>(parameter);
}
return {};
}
RefPtr<Expression> Parser::parse_column_name_expression(DeprecatedString with_parsed_identifier, bool with_parsed_period)
{
if (with_parsed_identifier.is_null() && !match(TokenType::Identifier))