From 891214470b357e3af531458fa9af19c79e10f50a Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 4 Oct 2022 15:33:51 +0800 Subject: [PATCH] Make limit getters available without unchecked. --- CHANGELOG.md | 1 + src/api/limits.rs | 50 +++++++++++++++++++---------------- src/api/mod.rs | 52 +++++++++++++++++++++++++++++++++++++ src/api/register.rs | 4 +-- src/eval/global_state.rs | 1 + src/eval/stmt.rs | 3 +-- src/func/script.rs | 1 - src/module/mod.rs | 4 +-- src/packages/blob_basic.rs | 2 -- src/packages/string_more.rs | 4 --- src/parser.rs | 2 -- 11 files changed, 87 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81e4c859..c1fe04c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Enhancements * `Scope` is now serializable and deserializable via `serde`. * `Scope` now contains a const generic parameter that allows specifying how many entries to be kept inline. * `parse_json` function is added to parse a JSON string into an object map. +* Methods return maximum limits (e.g. `max_string_len`) are now available even under `unchecked` in order to avoid unnecessary feature flags in third-party library code. Version 1.10.1 diff --git a/src/api/limits.rs b/src/api/limits.rs index 9c70c132..70de6592 100644 --- a/src/api/limits.rs +++ b/src/api/limits.rs @@ -94,12 +94,14 @@ impl Engine { } /// The maximum levels of function calls allowed for a script. /// - /// Not available under `unchecked` or `no_function`. - #[cfg(not(feature = "no_function"))] + /// Zero under `no_function`. #[inline(always)] #[must_use] pub const fn max_call_levels(&self) -> usize { - self.limits.max_call_stack_depth + #[cfg(not(feature = "no_function"))] + return self.limits.max_call_stack_depth; + #[cfg(feature = "no_function")] + return 0; } /// Set the maximum number of operations allowed for a script to run to avoid /// consuming too much resources (0 for unlimited). @@ -133,12 +135,14 @@ impl Engine { } /// The maximum number of imported [modules][crate::Module] allowed for a script. /// - /// Not available under `unchecked` or `no_module`. - #[cfg(not(feature = "no_module"))] + /// Zero under `no_module`. #[inline(always)] #[must_use] pub const fn max_modules(&self) -> usize { - self.limits.max_modules + #[cfg(not(feature = "no_module"))] + return self.limits.max_modules; + #[cfg(feature = "no_module")] + return 0; } /// Set the depth limits for expressions (0 for unlimited). /// @@ -157,8 +161,6 @@ impl Engine { self } /// The depth limit for expressions (0 for unlimited). - /// - /// Not available under `unchecked`. #[inline] #[must_use] pub const fn max_expr_depth(&self) -> usize { @@ -170,16 +172,18 @@ impl Engine { } /// The depth limit for expressions in functions (0 for unlimited). /// - /// Not available under `unchecked` or `no_function`. - #[cfg(not(feature = "no_function"))] + /// Zero under `no_function`. #[inline] #[must_use] pub const fn max_function_expr_depth(&self) -> usize { - if let Some(n) = self.limits.max_function_expr_depth { + #[cfg(not(feature = "no_function"))] + return if let Some(n) = self.limits.max_function_expr_depth { n.get() } else { 0 - } + }; + #[cfg(feature = "no_function")] + return 0; } /// Set the maximum length of [strings][crate::ImmutableString] (0 for unlimited). /// @@ -190,8 +194,6 @@ impl Engine { self } /// The maximum length of [strings][crate::ImmutableString] (0 for unlimited). - /// - /// Not available under `unchecked`. #[inline] #[must_use] pub const fn max_string_size(&self) -> usize { @@ -212,16 +214,18 @@ impl Engine { } /// The maximum length of [arrays][crate::Array] (0 for unlimited). /// - /// Not available under `unchecked` or `no_index`. - #[cfg(not(feature = "no_index"))] + /// Zero under `no_index`. #[inline] #[must_use] pub const fn max_array_size(&self) -> usize { - if let Some(n) = self.limits.max_array_size { + #[cfg(not(feature = "no_index"))] + return if let Some(n) = self.limits.max_array_size { n.get() } else { 0 - } + }; + #[cfg(feature = "no_index")] + return 0; } /// Set the maximum size of [object maps][crate::Map] (0 for unlimited). /// @@ -234,15 +238,17 @@ impl Engine { } /// The maximum size of [object maps][crate::Map] (0 for unlimited). /// - /// Not available under `unchecked` or `no_object`. - #[cfg(not(feature = "no_object"))] + /// Zero under `no_object`. #[inline] #[must_use] pub const fn max_map_size(&self) -> usize { - if let Some(n) = self.limits.max_map_size { + #[cfg(not(feature = "no_object"))] + return if let Some(n) = self.limits.max_map_size { n.get() } else { 0 - } + }; + #[cfg(feature = "no_object")] + return 0; } } diff --git a/src/api/mod.rs b/src/api/mod.rs index 6ddf090b..d98b0dd6 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -236,3 +236,55 @@ impl Engine { self } } + +#[cfg(feature = "unchecked")] +impl Engine { + /// The maximum levels of function calls allowed for a script. + #[inline(always)] + #[must_use] + pub const fn max_call_levels(&self) -> usize { + usize::MAX + } + /// The maximum number of operations allowed for a script to run (0 for unlimited). + #[inline] + #[must_use] + pub const fn max_operations(&self) -> u64 { + 0 + } + /// The maximum number of imported [modules][crate::Module] allowed for a script. + #[inline(always)] + #[must_use] + pub const fn max_modules(&self) -> usize { + usize::MAX + } + /// The depth limit for expressions (0 for unlimited). + #[inline(always)] + #[must_use] + pub const fn max_expr_depth(&self) -> usize { + 0 + } + /// The depth limit for expressions in functions (0 for unlimited). + #[inline(always)] + #[must_use] + pub const fn max_function_expr_depth(&self) -> usize { + 0 + } + /// The maximum length of [strings][crate::ImmutableString] (0 for unlimited). + #[inline(always)] + #[must_use] + pub const fn max_string_size(&self) -> usize { + 0 + } + /// The maximum length of [arrays][crate::Array] (0 for unlimited). + #[inline(always)] + #[must_use] + pub const fn max_array_size(&self) -> usize { + 0 + } + /// The maximum size of [object maps][crate::Map] (0 for unlimited). + #[inline(always)] + #[must_use] + pub const fn max_map_size(&self) -> usize { + 0 + } +} diff --git a/src/api/register.rs b/src/api/register.rs index 9095a31f..ce5c0c4a 100644 --- a/src/api/register.rs +++ b/src/api/register.rs @@ -226,12 +226,12 @@ impl Engine { #[inline(always)] pub fn register_type_with_name_raw( &mut self, - fully_qualified_type_path: impl Into, + type_path: impl Into, name: impl Into, ) -> &mut Self { // Add the pretty-print type name into the map self.global_namespace_mut() - .set_custom_type_raw(fully_qualified_type_path, name); + .set_custom_type_raw(type_path, name); self } /// Register a type iterator for an iterable type with the [`Engine`]. diff --git a/src/eval/global_state.rs b/src/eval/global_state.rs index 3d271af2..ef7edf84 100644 --- a/src/eval/global_state.rs +++ b/src/eval/global_state.rs @@ -36,6 +36,7 @@ pub struct GlobalRuntimeState<'a> { /// Number of operations performed. pub num_operations: u64, /// Number of modules loaded. + #[cfg(not(feature = "no_module"))] pub num_modules_loaded: usize, /// Level of the current scope. /// diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 018a6bf4..d62a39bb 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -738,7 +738,7 @@ impl Engine { #[cfg(feature = "no_object")] _ => { - err.take_position(); + let _ = err.take_position(); err.to_string().into() } #[cfg(not(feature = "no_object"))] @@ -924,7 +924,6 @@ impl Engine { let (expr, export) = &**x; // Guard against too many modules - #[cfg(not(feature = "unchecked"))] if global.num_modules_loaded >= self.max_modules() { return Err(ERR::ErrorTooManyModules(*_pos).into()); } diff --git a/src/func/script.rs b/src/func/script.rs index 8d8139d6..6d016cc5 100644 --- a/src/func/script.rs +++ b/src/func/script.rs @@ -67,7 +67,6 @@ impl Engine { self.inc_operations(&mut global.num_operations, pos)?; // Check for stack overflow - #[cfg(not(feature = "unchecked"))] if level > self.max_call_levels() { return Err(ERR::ErrorStackOverflow(pos).into()); } diff --git a/src/module/mod.rs b/src/module/mod.rs index 0479ee70..9e5afca5 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -494,12 +494,12 @@ impl Module { #[inline(always)] pub fn set_custom_type_raw( &mut self, - type_name: impl Into, + type_path: impl Into, name: impl Into, ) -> &mut Self { self.custom_types .get_or_insert_with(CustomTypesCollection::new) - .add(type_name, name); + .add(type_path, name); self } /// Get the display name of a registered custom type. diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index 4b6639c2..4ddd68b6 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -79,7 +79,6 @@ pub mod blob_functions { let _ctx = ctx; // Check if blob will be over max size limit - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_array_size() > 0 && len > _ctx.engine().max_array_size() { return Err( crate::ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into(), @@ -364,7 +363,6 @@ pub mod blob_functions { let _ctx = ctx; // Check if blob will be over max size limit - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_array_size() > 0 && len > _ctx.engine().max_array_size() { return Err( crate::ERR::ErrorDataTooLarge("Size of BLOB".to_string(), Position::NONE).into(), diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs index 93e8edf4..cfaf3e83 100644 --- a/src/packages/string_more.rs +++ b/src/packages/string_more.rs @@ -1216,7 +1216,6 @@ mod string_functions { let _ctx = ctx; // Check if string will be over max size limit - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() { return Err(crate::ERR::ErrorDataTooLarge( "Length of string".to_string(), @@ -1234,7 +1233,6 @@ mod string_functions { p.push(character); } - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() { return Err(crate::ERR::ErrorDataTooLarge( @@ -1278,7 +1276,6 @@ mod string_functions { let _ctx = ctx; // Check if string will be over max size limit - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && len > _ctx.engine().max_string_size() { return Err(crate::ERR::ErrorDataTooLarge( "Length of string".to_string(), @@ -1303,7 +1300,6 @@ mod string_functions { } } - #[cfg(not(feature = "unchecked"))] if _ctx.engine().max_string_size() > 0 && string.len() > _ctx.engine().max_string_size() { return Err(crate::ERR::ErrorDataTooLarge( diff --git a/src/parser.rs b/src/parser.rs index 0ec27614..77037327 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -906,7 +906,6 @@ impl Engine { loop { const MISSING_RBRACKET: &str = "to end this array literal"; - #[cfg(not(feature = "unchecked"))] if self.max_array_size() > 0 && array.len() >= self.max_array_size() { return Err(PERR::LiteralTooLarge( "Size of array literal".to_string(), @@ -1043,7 +1042,6 @@ impl Engine { } }; - #[cfg(not(feature = "unchecked"))] if self.max_map_size() > 0 && map.len() >= self.max_map_size() { return Err(PERR::LiteralTooLarge( "Number of properties in object map literal".to_string(),