Make query depth limits configurable (#4787)
This commit is contained in:
parent
682523db6d
commit
e5e4783e3f
2 changed files with 40 additions and 11 deletions
|
@ -21,6 +21,14 @@ pub static MAX_CONCURRENT_TASKS: LazyLock<usize> =
|
||||||
pub static MAX_COMPUTATION_DEPTH: LazyLock<u32> =
|
pub static MAX_COMPUTATION_DEPTH: LazyLock<u32> =
|
||||||
lazy_env_parse!("SURREAL_MAX_COMPUTATION_DEPTH", u32, 120);
|
lazy_env_parse!("SURREAL_MAX_COMPUTATION_DEPTH", u32, 120);
|
||||||
|
|
||||||
|
/// Specifies how deep the parser will parse nested objects and arrays in a query.
|
||||||
|
pub static MAX_OBJECT_PARSING_DEPTH: LazyLock<u32> =
|
||||||
|
lazy_env_parse!("SURREAL_MAX_OBJECT_PARSING_DEPTH", u32, 100);
|
||||||
|
|
||||||
|
/// Specifies how deep the parser will parse recursive queries (queries within queries).
|
||||||
|
pub static MAX_QUERY_PARSING_DEPTH: LazyLock<u32> =
|
||||||
|
lazy_env_parse!("SURREAL_MAX_QUERY_PARSING_DEPTH", u32, 20);
|
||||||
|
|
||||||
/// Specifies the number of items which can be cached within a single transaction.
|
/// Specifies the number of items which can be cached within a single transaction.
|
||||||
pub static TRANSACTION_CACHE_SIZE: LazyLock<usize> =
|
pub static TRANSACTION_CACHE_SIZE: LazyLock<usize> =
|
||||||
lazy_env_parse!("SURREAL_TRANSACTION_CACHE_SIZE", usize, 10_000);
|
lazy_env_parse!("SURREAL_TRANSACTION_CACHE_SIZE", usize, 10_000);
|
||||||
|
@ -61,8 +69,10 @@ pub static EXTERNAL_SORTING_BUFFER_LIMIT: LazyLock<usize> =
|
||||||
pub static GRAPHQL_ENABLE: LazyLock<bool> =
|
pub static GRAPHQL_ENABLE: LazyLock<bool> =
|
||||||
lazy_env_parse!("SURREAL_EXPERIMENTAL_GRAPHQL", bool, false);
|
lazy_env_parse!("SURREAL_EXPERIMENTAL_GRAPHQL", bool, false);
|
||||||
|
|
||||||
/// Enable experimental bearer access and stateful access grant management. Still under active development.
|
/// Enable experimental bearer access and stateful access grant management.
|
||||||
/// Using this experimental feature may introduce risks related to breaking changes and security issues.
|
///
|
||||||
|
/// Still under active development. Using this experimental feature may introduce risks related
|
||||||
|
/// to breaking changes and security issues.
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
pub static EXPERIMENTAL_BEARER_ACCESS: LazyLock<bool> =
|
pub static EXPERIMENTAL_BEARER_ACCESS: LazyLock<bool> =
|
||||||
lazy_env_parse!("SURREAL_EXPERIMENTAL_BEARER_ACCESS", bool, false);
|
lazy_env_parse!("SURREAL_EXPERIMENTAL_BEARER_ACCESS", bool, false);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Module containing the implementation of the surrealql tokens, lexer, and parser.
|
//! Module containing the implementation of the surrealql tokens, lexer, and parser.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
cnf::{MAX_OBJECT_PARSING_DEPTH, MAX_QUERY_PARSING_DEPTH},
|
||||||
err::Error,
|
err::Error,
|
||||||
sql::{Block, Datetime, Duration, Idiom, Query, Range, Subquery, Thing, Value},
|
sql::{Block, Datetime, Duration, Idiom, Query, Range, Subquery, Thing, Value},
|
||||||
};
|
};
|
||||||
|
@ -43,7 +44,9 @@ pub fn could_be_reserved_keyword(s: &str) -> bool {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn parse(input: &str) -> Result<Query, Error> {
|
pub fn parse(input: &str) -> Result<Query, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL query");
|
trace!(target: TARGET, "Parsing SurrealQL query");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
.enter(|stk| parser.parse_query(stk))
|
.enter(|stk| parser.parse_query(stk))
|
||||||
|
@ -56,7 +59,9 @@ pub fn parse(input: &str) -> Result<Query, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn value(input: &str) -> Result<Value, Error> {
|
pub fn value(input: &str) -> Result<Value, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL value");
|
trace!(target: TARGET, "Parsing SurrealQL value");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
.enter(|stk| parser.parse_value_table(stk))
|
.enter(|stk| parser.parse_value_table(stk))
|
||||||
|
@ -70,7 +75,9 @@ pub fn value(input: &str) -> Result<Value, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn json(input: &str) -> Result<Value, Error> {
|
pub fn json(input: &str) -> Result<Value, Error> {
|
||||||
trace!(target: TARGET, "Parsing inert JSON value");
|
trace!(target: TARGET, "Parsing inert JSON value");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
.enter(|stk| parser.parse_json(stk))
|
.enter(|stk| parser.parse_json(stk))
|
||||||
|
@ -84,7 +91,9 @@ pub fn json(input: &str) -> Result<Value, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn subquery(input: &str) -> Result<Subquery, Error> {
|
pub fn subquery(input: &str) -> Result<Subquery, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL subquery");
|
trace!(target: TARGET, "Parsing SurrealQL subquery");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
.enter(|stk| parser.parse_full_subquery(stk))
|
.enter(|stk| parser.parse_full_subquery(stk))
|
||||||
|
@ -98,7 +107,9 @@ pub fn subquery(input: &str) -> Result<Subquery, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn idiom(input: &str) -> Result<Idiom, Error> {
|
pub fn idiom(input: &str) -> Result<Idiom, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL idiom");
|
trace!(target: TARGET, "Parsing SurrealQL idiom");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
parser.table_as_field = true;
|
parser.table_as_field = true;
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
|
@ -151,7 +162,9 @@ pub fn range(input: &str) -> Result<Range, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn thing(input: &str) -> Result<Thing, Error> {
|
pub fn thing(input: &str) -> Result<Thing, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL thing");
|
trace!(target: TARGET, "Parsing SurrealQL thing");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
stack
|
stack
|
||||||
.enter(|stk| parser.parse_thing(stk))
|
.enter(|stk| parser.parse_thing(stk))
|
||||||
|
@ -165,7 +178,9 @@ pub fn thing(input: &str) -> Result<Thing, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn block(input: &str) -> Result<Block, Error> {
|
pub fn block(input: &str) -> Result<Block, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL block");
|
trace!(target: TARGET, "Parsing SurrealQL block");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
let token = parser.peek();
|
let token = parser.peek();
|
||||||
match token.kind {
|
match token.kind {
|
||||||
|
@ -190,7 +205,9 @@ pub fn block(input: &str) -> Result<Block, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn value_legacy_strand(input: &str) -> Result<Value, Error> {
|
pub fn value_legacy_strand(input: &str) -> Result<Value, Error> {
|
||||||
trace!(target: TARGET, "Parsing SurrealQL value, with legacy strings");
|
trace!(target: TARGET, "Parsing SurrealQL value, with legacy strings");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
parser.allow_legacy_strand(true);
|
parser.allow_legacy_strand(true);
|
||||||
stack
|
stack
|
||||||
|
@ -205,7 +222,9 @@ pub fn value_legacy_strand(input: &str) -> Result<Value, Error> {
|
||||||
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
#[instrument(level = "trace", target = "surrealdb::core::syn", fields(length = input.len()))]
|
||||||
pub fn json_legacy_strand(input: &str) -> Result<Value, Error> {
|
pub fn json_legacy_strand(input: &str) -> Result<Value, Error> {
|
||||||
trace!(target: TARGET, "Parsing inert JSON value, with legacy strings");
|
trace!(target: TARGET, "Parsing inert JSON value, with legacy strings");
|
||||||
let mut parser = Parser::new(input.as_bytes());
|
let mut parser = Parser::new(input.as_bytes())
|
||||||
|
.with_object_recursion_limit(*MAX_OBJECT_PARSING_DEPTH as usize)
|
||||||
|
.with_query_recursion_limit(*MAX_QUERY_PARSING_DEPTH as usize);
|
||||||
let mut stack = Stack::new();
|
let mut stack = Stack::new();
|
||||||
parser.allow_legacy_strand(true);
|
parser.allow_legacy_strand(true);
|
||||||
stack
|
stack
|
||||||
|
|
Loading…
Reference in a new issue