Use NonZero for limits.

This commit is contained in:
Stephen Chung 2021-01-06 13:46:53 +08:00
parent 3fbcefe0ed
commit a5d6392107
4 changed files with 119 additions and 112 deletions

View File

@ -135,7 +135,8 @@ impl Imports {
.rev() .rev()
.find_map(|(_, m)| m.get_qualified_fn(hash).map(|f| (f, m.id_raw()))) .find_map(|(_, m)| m.get_qualified_fn(hash).map(|f| (f, m.id_raw())))
} }
/// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of imported [modules][Module]? /// Does the specified [`TypeId`][std::any::TypeId] iterator exist in this stack of
/// imported [modules][Module]?
#[allow(dead_code)] #[allow(dead_code)]
#[inline(always)] #[inline(always)]
pub fn contains_iter(&self, id: TypeId) -> bool { pub fn contains_iter(&self, id: TypeId) -> bool {
@ -508,8 +509,8 @@ pub struct State {
/// In some situation, e.g. after running an `eval` statement, subsequent offsets become mis-aligned. /// In some situation, e.g. after running an `eval` statement, subsequent offsets become mis-aligned.
/// When that happens, this flag is turned on to force a scope lookup by name. /// When that happens, this flag is turned on to force a scope lookup by name.
pub always_search: bool, pub always_search: bool,
/// Level of the current scope. The global (root) level is zero, a new block (or function call) /// Level of the current scope. The global (root) level is zero, a new block
/// is one level higher, and so on. /// (or function call) is one level higher, and so on.
pub scope_level: usize, pub scope_level: usize,
/// Number of operations performed. /// Number of operations performed.
pub operations: u64, pub operations: u64,
@ -542,30 +543,34 @@ impl State {
pub struct Limits { pub struct Limits {
/// Maximum levels of call-stack to prevent infinite recursion. /// Maximum levels of call-stack to prevent infinite recursion.
/// Not available under `no_function`. /// Not available under `no_function`.
///
/// Set to zero to effectively disable function calls.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
pub max_call_stack_depth: usize, pub max_call_stack_depth: usize,
/// Maximum depth of statements/expressions at global level (0 = unlimited). /// Maximum depth of statements/expressions at global level.
pub max_expr_depth: usize, pub max_expr_depth: Option<NonZeroUsize>,
/// Maximum depth of statements/expressions in functions (0 = unlimited). /// Maximum depth of statements/expressions in functions.
/// Not available under `no_function`. /// Not available under `no_function`.
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
pub max_function_expr_depth: usize, pub max_function_expr_depth: Option<NonZeroUsize>,
/// Maximum number of operations allowed to run (0 = unlimited). /// Maximum number of operations allowed to run.
pub max_operations: u64, pub max_operations: Option<NonZeroU64>,
/// Maximum number of [modules][Module] allowed to load. /// Maximum number of [modules][Module] allowed to load.
/// Not available under `no_module`. /// Not available under `no_module`.
///
/// Set to zero to effectively disable loading any [module][Module].
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
pub max_modules: usize, pub max_modules: usize,
/// Maximum length of a [string][ImmutableString] (0 = unlimited). /// Maximum length of a [string][ImmutableString].
pub max_string_size: usize, pub max_string_size: Option<NonZeroUsize>,
/// Maximum length of an [array][Array] (0 = unlimited). /// Maximum length of an [array][Array].
/// Not available under `no_index`. /// Not available under `no_index`.
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
pub max_array_size: usize, pub max_array_size: Option<NonZeroUsize>,
/// Maximum number of properties in an [object map][Map] (0 = unlimited). /// Maximum number of properties in an [object map][Map].
/// Not available under `no_object`. /// Not available under `no_object`.
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
pub max_map_size: usize, pub max_map_size: Option<NonZeroUsize>,
} }
/// Context of a script evaluation process. /// Context of a script evaluation process.
@ -777,13 +782,13 @@ pub fn search_imports(
// Qualified - check if the root module is directly indexed // Qualified - check if the root module is directly indexed
let index = if state.always_search { let index = if state.always_search {
0 None
} else { } else {
namespace.index().map_or(0, NonZeroUsize::get) namespace.index()
}; };
Ok(if index > 0 { Ok(if let Some(index) = index {
let offset = mods.len() - index; let offset = mods.len() - index.get();
mods.get(offset).expect("invalid index in Imports") mods.get(offset).expect("invalid index in Imports")
} else { } else {
mods.find(root) mods.find(root)
@ -838,17 +843,17 @@ impl Engine {
limits: Limits { limits: Limits {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_call_stack_depth: MAX_CALL_STACK_DEPTH, max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH, max_expr_depth: NonZeroUsize::new(MAX_EXPR_DEPTH),
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH, max_function_expr_depth: NonZeroUsize::new(MAX_FUNCTION_EXPR_DEPTH),
max_operations: 0, max_operations: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
max_modules: usize::MAX, max_modules: usize::MAX,
max_string_size: 0, max_string_size: None,
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
max_array_size: 0, max_array_size: None,
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
max_map_size: 0, max_map_size: None,
}, },
disable_doc_comments: false, disable_doc_comments: false,
@ -895,17 +900,17 @@ impl Engine {
limits: Limits { limits: Limits {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_call_stack_depth: MAX_CALL_STACK_DEPTH, max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH, max_expr_depth: NonZeroUsize::new(MAX_EXPR_DEPTH),
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH, max_function_expr_depth: NonZeroUsize::new(MAX_FUNCTION_EXPR_DEPTH),
max_operations: 0, max_operations: None,
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
max_modules: usize::MAX, max_modules: usize::MAX,
max_string_size: 0, max_string_size: None,
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
max_array_size: 0, max_array_size: None,
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
max_map_size: 0, max_map_size: None,
}, },
disable_doc_comments: false, disable_doc_comments: false,
@ -975,14 +980,11 @@ impl Engine {
} }
// Check if it is directly indexed // Check if it is directly indexed
let index = if state.always_search { let index = if state.always_search { &None } else { index };
0
} else {
index.map_or(0, NonZeroUsize::get)
};
// Check the variable resolver, if any // Check the variable resolver, if any
if let Some(ref resolve_var) = self.resolve_var { if let Some(ref resolve_var) = self.resolve_var {
let index = index.map(NonZeroUsize::get).unwrap_or(0);
let context = EvalContext { let context = EvalContext {
engine: self, engine: self,
scope, scope,
@ -1000,8 +1002,8 @@ impl Engine {
} }
} }
let index = if index > 0 { let index = if let Some(index) = index {
scope.len() - index scope.len() - index.get()
} else { } else {
// Find the variable in the scope // Find the variable in the scope
scope scope
@ -1012,8 +1014,8 @@ impl Engine {
let val = scope.get_mut_by_index(index); let val = scope.get_mut_by_index(index);
// Check for data race - probably not necessary because the only place it should conflict is in a method call // Check for data race - probably not necessary because the only place it should conflict is
// when the object variable is also used as a parameter. // in a method call when the object variable is also used as a parameter.
// if cfg!(not(feature = "no_closure")) && val.is_locked() { // if cfg!(not(feature = "no_closure")) && val.is_locked() {
// return EvalAltResult::ErrorDataRace(name.into(), *pos).into(); // return EvalAltResult::ErrorDataRace(name.into(), *pos).into();
// } // }
@ -1285,7 +1287,8 @@ impl Engine {
) )
.or_else( .or_else(
|err| match *err { |err| match *err {
// If there is no setter, no need to feed it back because the property is read-only // If there is no setter, no need to feed it back because
// the property is read-only
EvalAltResult::ErrorDotExpr(_, _) => { EvalAltResult::ErrorDotExpr(_, _) => {
Ok((Dynamic::UNIT, false)) Ok((Dynamic::UNIT, false))
} }
@ -1405,7 +1408,8 @@ impl Engine {
} }
/// Evaluate a chain of indexes and store the results in a [`StaticVec`]. /// Evaluate a chain of indexes and store the results in a [`StaticVec`].
/// [`StaticVec`] is used to avoid an allocation in the overwhelming cases of just a few levels of indexing. /// [`StaticVec`] is used to avoid an allocation in the overwhelming cases of
/// just a few levels of indexing.
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
fn eval_indexed_chain( fn eval_indexed_chain(
&self, &self,
@ -2400,20 +2404,23 @@ impl Engine {
result: Result<Dynamic, Box<EvalAltResult>>, result: Result<Dynamic, Box<EvalAltResult>>,
pos: Position, pos: Position,
) -> Result<Dynamic, Box<EvalAltResult>> { ) -> Result<Dynamic, Box<EvalAltResult>> {
// If no data size limits, just return // Simply return all errors
let mut total = 0; if result.is_err() {
return result;
}
total += self.max_string_size(); // If no data size limits, just return
let mut has_limit = self.limits.max_string_size.is_some();
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
{ {
total += self.max_array_size(); has_limit = has_limit || self.limits.max_array_size.is_some();
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
{ {
total += self.max_map_size(); has_limit = has_limit || self.limits.max_map_size.is_some();
} }
if total == 0 { if !has_limit {
return result; return result;
} }
@ -2469,34 +2476,33 @@ impl Engine {
} }
} }
match result {
// Simply return all errors
Err(_) => return result,
// String with limit
Ok(Dynamic(Union::Str(_, _))) if self.max_string_size() > 0 => (),
// Array with limit
#[cfg(not(feature = "no_index"))]
Ok(Dynamic(Union::Array(_, _))) if self.max_array_size() > 0 => (),
// Map with limit
#[cfg(not(feature = "no_object"))]
Ok(Dynamic(Union::Map(_, _))) if self.max_map_size() > 0 => (),
// Everything else is simply returned
Ok(_) => return result,
};
let (_arr, _map, s) = calc_size(result.as_ref().unwrap()); let (_arr, _map, s) = calc_size(result.as_ref().unwrap());
if s > self.max_string_size() { if s > self
.limits
.max_string_size
.map_or(usize::MAX, NonZeroUsize::get)
{
return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), pos).into(); return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), pos).into();
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
if _arr > self.max_array_size() { if _arr
> self
.limits
.max_array_size
.map_or(usize::MAX, NonZeroUsize::get)
{
return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), pos).into(); return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), pos).into();
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
if _map > self.max_map_size() { if _map
> self
.limits
.max_map_size
.map_or(usize::MAX, NonZeroUsize::get)
{
return EvalAltResult::ErrorDataTooLarge("Size of object map".to_string(), pos).into(); return EvalAltResult::ErrorDataTooLarge("Size of object map".to_string(), pos).into();
} }

View File

@ -1,6 +1,10 @@
//! Configuration settings for [`Engine`]. //! Configuration settings for [`Engine`].
use crate::stdlib::{format, num::NonZeroU8, string::String}; use crate::stdlib::{
format,
num::{NonZeroU64, NonZeroU8, NonZeroUsize},
string::String,
};
use crate::token::Token; use crate::token::Token;
use crate::Engine; use crate::Engine;
@ -62,11 +66,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline(always)] #[inline(always)]
pub fn set_max_operations(&mut self, operations: u64) -> &mut Self { pub fn set_max_operations(&mut self, operations: u64) -> &mut Self {
self.limits.max_operations = if operations == u64::MAX { self.limits.max_operations = NonZeroU64::new(operations);
0
} else {
operations
};
self self
} }
/// The maximum number of operations allowed for a script to run (0 for unlimited). /// The maximum number of operations allowed for a script to run (0 for unlimited).
@ -75,7 +75,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline(always)] #[inline(always)]
pub fn max_operations(&self) -> u64 { pub fn max_operations(&self) -> u64 {
self.limits.max_operations self.limits.max_operations.map_or(0, NonZeroU64::get)
} }
/// Set the maximum number of imported [modules][crate::Module] allowed for a script. /// Set the maximum number of imported [modules][crate::Module] allowed for a script.
/// ///
@ -106,18 +106,10 @@ impl Engine {
max_expr_depth: usize, max_expr_depth: usize,
#[cfg(not(feature = "no_function"))] max_function_expr_depth: usize, #[cfg(not(feature = "no_function"))] max_function_expr_depth: usize,
) -> &mut Self { ) -> &mut Self {
self.limits.max_expr_depth = if max_expr_depth == usize::MAX { self.limits.max_expr_depth = NonZeroUsize::new(max_expr_depth);
0
} else {
max_expr_depth
};
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
{ {
self.limits.max_function_expr_depth = if max_function_expr_depth == usize::MAX { self.limits.max_function_expr_depth = NonZeroUsize::new(max_function_expr_depth);
0
} else {
max_function_expr_depth
};
} }
self self
} }
@ -127,7 +119,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline(always)] #[inline(always)]
pub fn max_expr_depth(&self) -> usize { pub fn max_expr_depth(&self) -> usize {
self.limits.max_expr_depth self.limits.max_expr_depth.map_or(0, NonZeroUsize::get)
} }
/// The depth limit for expressions in functions (0 for unlimited). /// The depth limit for expressions in functions (0 for unlimited).
/// ///
@ -136,7 +128,9 @@ impl Engine {
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
#[inline(always)] #[inline(always)]
pub fn max_function_expr_depth(&self) -> usize { pub fn max_function_expr_depth(&self) -> usize {
self.limits.max_function_expr_depth self.limits
.max_function_expr_depth
.map_or(0, NonZeroUsize::get)
} }
/// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited). /// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited).
/// ///
@ -144,7 +138,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline(always)] #[inline(always)]
pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self { pub fn set_max_string_size(&mut self, max_size: usize) -> &mut Self {
self.limits.max_string_size = if max_size == usize::MAX { 0 } else { max_size }; self.limits.max_string_size = NonZeroUsize::new(max_size);
self self
} }
/// The maximum length of [strings][crate::ImmutableString] (0 for unlimited). /// The maximum length of [strings][crate::ImmutableString] (0 for unlimited).
@ -153,7 +147,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline(always)] #[inline(always)]
pub fn max_string_size(&self) -> usize { pub fn max_string_size(&self) -> usize {
self.limits.max_string_size self.limits.max_string_size.map_or(0, NonZeroUsize::get)
} }
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited). /// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
/// ///
@ -162,7 +156,7 @@ impl Engine {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[inline(always)] #[inline(always)]
pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self { pub fn set_max_array_size(&mut self, max_size: usize) -> &mut Self {
self.limits.max_array_size = if max_size == usize::MAX { 0 } else { max_size }; self.limits.max_array_size = NonZeroUsize::new(max_size);
self self
} }
/// The maximum length of [arrays][crate::Array] (0 for unlimited). /// The maximum length of [arrays][crate::Array] (0 for unlimited).
@ -172,7 +166,7 @@ impl Engine {
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
#[inline(always)] #[inline(always)]
pub fn max_array_size(&self) -> usize { pub fn max_array_size(&self) -> usize {
self.limits.max_array_size self.limits.max_array_size.map_or(0, NonZeroUsize::get)
} }
/// Set the maximum size of [object maps][crate::Map] (0 for unlimited). /// Set the maximum size of [object maps][crate::Map] (0 for unlimited).
/// ///
@ -181,7 +175,7 @@ impl Engine {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline(always)] #[inline(always)]
pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self { pub fn set_max_map_size(&mut self, max_size: usize) -> &mut Self {
self.limits.max_map_size = if max_size == usize::MAX { 0 } else { max_size }; self.limits.max_map_size = NonZeroUsize::new(max_size);
self self
} }
/// The maximum size of [object maps][crate::Map] (0 for unlimited). /// The maximum size of [object maps][crate::Map] (0 for unlimited).
@ -191,7 +185,7 @@ impl Engine {
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
#[inline(always)] #[inline(always)]
pub fn max_map_size(&self) -> usize { pub fn max_map_size(&self) -> usize {
self.limits.max_map_size self.limits.max_map_size.map_or(0, NonZeroUsize::get)
} }
/// Set the module resolution service used by the [`Engine`]. /// Set the module resolution service used by the [`Engine`].
/// ///

View File

@ -61,11 +61,11 @@ struct ParseState<'e> {
modules: StaticVec<ImmutableString>, modules: StaticVec<ImmutableString>,
/// Maximum levels of expression nesting. /// Maximum levels of expression nesting.
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
max_expr_depth: usize, max_expr_depth: Option<NonZeroUsize>,
/// Maximum levels of expression nesting in functions. /// Maximum levels of expression nesting in functions.
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_function_expr_depth: usize, max_function_expr_depth: Option<NonZeroUsize>,
} }
impl<'e> ParseState<'e> { impl<'e> ParseState<'e> {
@ -73,10 +73,10 @@ impl<'e> ParseState<'e> {
#[inline(always)] #[inline(always)]
pub fn new( pub fn new(
engine: &'e Engine, engine: &'e Engine,
#[cfg(not(feature = "unchecked"))] max_expr_depth: usize, #[cfg(not(feature = "unchecked"))] max_expr_depth: Option<NonZeroUsize>,
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
max_function_expr_depth: usize, max_function_expr_depth: Option<NonZeroUsize>,
) -> Self { ) -> Self {
Self { Self {
engine, engine,
@ -212,15 +212,17 @@ impl ParseSettings {
} }
/// Make sure that the current level of expression nesting is within the maximum limit. /// Make sure that the current level of expression nesting is within the maximum limit.
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[inline] #[inline(always)]
pub fn ensure_level_within_max_limit(&self, limit: usize) -> Result<(), ParseError> { pub fn ensure_level_within_max_limit(
if limit == 0 { &self,
Ok(()) limit: Option<NonZeroUsize>,
} else if self.level > limit { ) -> Result<(), ParseError> {
Err(PERR::ExprTooDeep.into_err(self.pos)) if let Some(limit) = limit {
} else { if self.level > limit.get() {
Ok(()) return Err(PERR::ExprTooDeep.into_err(self.pos));
}
} }
Ok(())
} }
} }
@ -3040,10 +3042,10 @@ impl Engine {
let mut state = ParseState::new( let mut state = ParseState::new(
self, self,
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
self.max_expr_depth(), NonZeroUsize::new(self.max_expr_depth()),
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
self.max_function_expr_depth(), NonZeroUsize::new(self.max_function_expr_depth()),
); );
let settings = ParseSettings { let settings = ParseSettings {
@ -3087,10 +3089,10 @@ impl Engine {
let mut state = ParseState::new( let mut state = ParseState::new(
self, self,
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
self.max_expr_depth(), NonZeroUsize::new(self.max_expr_depth()),
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
#[cfg(not(feature = "no_function"))] #[cfg(not(feature = "no_function"))]
self.max_function_expr_depth(), NonZeroUsize::new(self.max_function_expr_depth()),
); );
while !input.peek().unwrap().0.is_eof() { while !input.peek().unwrap().0.is_eof() {

View File

@ -8,6 +8,7 @@ use crate::stdlib::{
borrow::Cow, borrow::Cow,
char, fmt, format, char, fmt, format,
iter::Peekable, iter::Peekable,
num::NonZeroUsize,
str::{Chars, FromStr}, str::{Chars, FromStr},
string::{String, ToString}, string::{String, ToString},
}; };
@ -747,7 +748,7 @@ impl From<Token> for String {
#[derive(Debug, Clone, Eq, PartialEq, Default)] #[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct TokenizeState { pub struct TokenizeState {
/// Maximum length of a string (0 = unlimited). /// Maximum length of a string (0 = unlimited).
pub max_string_size: usize, pub max_string_size: Option<NonZeroUsize>,
/// Can the next token be a unary operator? /// Can the next token be a unary operator?
pub non_unary: bool, pub non_unary: bool,
/// Is the tokenizer currently inside a block comment? /// Is the tokenizer currently inside a block comment?
@ -796,8 +797,10 @@ pub fn parse_string_literal(
pos.advance(); pos.advance();
if state.max_string_size > 0 && result.len() > state.max_string_size { if let Some(max) = state.max_string_size {
return Err((LexError::StringTooLong(state.max_string_size), *pos)); if result.len() > max.get() {
return Err((LexError::StringTooLong(max.get()), *pos));
}
} }
match next_char { match next_char {
@ -902,8 +905,10 @@ pub fn parse_string_literal(
let s = result.iter().collect::<String>(); let s = result.iter().collect::<String>();
if state.max_string_size > 0 && s.len() > state.max_string_size { if let Some(max) = state.max_string_size {
return Err((LexError::StringTooLong(state.max_string_size), *pos)); if s.len() > max.get() {
return Err((LexError::StringTooLong(max.get()), *pos));
}
} }
Ok(s) Ok(s)