Avoid warnings.

This commit is contained in:
Stephen Chung
2020-07-26 13:51:09 +08:00
parent 5e48478496
commit e7af008d74
24 changed files with 464 additions and 225 deletions

View File

@@ -4,10 +4,10 @@ use crate::any::{map_std_type_name, Dynamic, Union, Variant};
use crate::calc_fn_hash;
use crate::fn_call::run_builtin_op_assignment;
use crate::fn_native::{CallableFunction, Callback, FnPtr};
use crate::module::{resolvers, Module, ModuleRef, ModuleResolver};
use crate::module::{Module, ModuleRef};
use crate::optimize::OptimizationLevel;
use crate::packages::{Package, PackagesCollection, StandardPackage};
use crate::parser::{Expr, FnAccess, ImmutableString, ReturnType, ScriptFnDef, Stmt};
use crate::parser::{Expr, ImmutableString, ReturnType, Stmt};
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
use crate::result::EvalAltResult;
use crate::scope::{EntryType as ScopeEntryType, Scope};
@@ -15,8 +15,13 @@ use crate::syntax::{CustomSyntax, EvalContext};
use crate::token::Position;
use crate::utils::StaticVec;
#[cfg(not(feature = "no_function"))]
use crate::parser::{FnAccess, ScriptFnDef};
#[cfg(not(feature = "no_module"))]
use crate::module::{resolvers, ModuleResolver};
use crate::stdlib::{
any::TypeId,
borrow::Cow,
boxed::Box,
collections::{HashMap, HashSet},
@@ -26,6 +31,9 @@ use crate::stdlib::{
vec::Vec,
};
#[cfg(not(feature = "no_index"))]
use crate::stdlib::any::TypeId;
/// Variable-sized array of `Dynamic` values.
///
/// Not available under the `no_index` feature.
@@ -66,13 +74,6 @@ pub const MAX_EXPR_DEPTH: usize = 128;
#[cfg(not(debug_assertions))]
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 32;
#[cfg(feature = "unchecked")]
pub const MAX_CALL_STACK_DEPTH: usize = usize::MAX;
#[cfg(feature = "unchecked")]
pub const MAX_EXPR_DEPTH: usize = 0;
#[cfg(feature = "unchecked")]
pub const MAX_FUNCTION_EXPR_DEPTH: usize = 0;
pub const KEYWORD_PRINT: &str = "print";
pub const KEYWORD_DEBUG: &str = "debug";
pub const KEYWORD_TYPE_OF: &str = "type_of";
@@ -86,6 +87,7 @@ pub const FN_GET: &str = "get$";
pub const FN_SET: &str = "set$";
pub const FN_IDX_GET: &str = "index$get$";
pub const FN_IDX_SET: &str = "index$set$";
#[cfg(not(feature = "no_function"))]
pub const FN_ANONYMOUS: &str = "anon$";
pub const MARKER_EXPR: &str = "$expr$";
pub const MARKER_BLOCK: &str = "$block$";
@@ -108,6 +110,7 @@ pub enum Target<'a> {
Value(Dynamic),
/// The target is a character inside a String.
/// This is necessary because directly pointing to a char inside a String is impossible.
#[cfg(not(feature = "no_index"))]
StringChar(&'a mut Dynamic, usize, Dynamic),
}
@@ -116,7 +119,9 @@ impl Target<'_> {
pub fn is_ref(&self) -> bool {
match self {
Self::Ref(_) => true,
Self::Value(_) | Self::StringChar(_, _, _) => false,
Self::Value(_) => false,
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, _) => false,
}
}
/// Is the `Target` an owned value?
@@ -124,6 +129,7 @@ impl Target<'_> {
match self {
Self::Ref(_) => false,
Self::Value(_) => true,
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, _) => false,
}
}
@@ -132,14 +138,16 @@ impl Target<'_> {
match self {
Target::Ref(r) => r.is::<T>(),
Target::Value(r) => r.is::<T>(),
#[cfg(not(feature = "no_index"))]
Target::StringChar(_, _, _) => TypeId::of::<T>() == TypeId::of::<char>(),
}
}
/// Get the value of the `Target` as a `Dynamic`, cloning a referenced value if necessary.
pub fn clone_into_dynamic(self) -> Dynamic {
match self {
Self::Ref(r) => r.clone(), // Referenced value is cloned
Self::Value(v) => v, // Owned value is simply taken
Self::Ref(r) => r.clone(), // Referenced value is cloned
Self::Value(v) => v, // Owned value is simply taken
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, ch) => ch, // Character is taken
}
}
@@ -148,6 +156,7 @@ impl Target<'_> {
match self {
Self::Ref(r) => *r,
Self::Value(ref mut r) => r,
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, ref mut r) => r,
}
}
@@ -161,6 +170,7 @@ impl Target<'_> {
Position::none(),
)))
}
#[cfg(not(feature = "no_index"))]
Self::StringChar(Dynamic(Union::Str(ref mut s)), index, _) => {
// Replace the character at the specified index position
let new_ch = new_val
@@ -176,7 +186,8 @@ impl Target<'_> {
*s = chars.iter().collect::<String>().into();
}
}
_ => unreachable!(),
#[cfg(not(feature = "no_index"))]
Self::StringChar(_, _, _) => unreachable!(),
}
Ok(())
@@ -249,6 +260,34 @@ pub fn get_script_function_by_signature<'a>(
}
}
/// [INTERNALS] A type containing all the limits imposed by the `Engine`.
/// Exported under the `internals` feature only.
///
/// ## WARNING
///
/// This type is volatile and may change.
#[cfg(not(feature = "unchecked"))]
pub struct Limits {
/// Maximum levels of call-stack to prevent infinite recursion.
///
/// Defaults to 16 for debug builds and 128 for non-debug builds.
pub max_call_stack_depth: usize,
/// Maximum depth of statements/expressions at global level.
pub max_expr_depth: usize,
/// Maximum depth of statements/expressions in functions.
pub max_function_expr_depth: usize,
/// Maximum number of operations allowed to run.
pub max_operations: u64,
/// Maximum number of modules allowed to load.
pub max_modules: usize,
/// Maximum length of a string.
pub max_string_size: usize,
/// Maximum length of an array.
pub max_array_size: usize,
/// Maximum number of properties in a map.
pub max_map_size: usize,
}
/// Rhai main scripting engine.
///
/// ```
@@ -275,6 +314,7 @@ pub struct Engine {
pub(crate) packages: PackagesCollection,
/// A module resolution service.
#[cfg(not(feature = "no_module"))]
pub(crate) module_resolver: Option<Box<dyn ModuleResolver>>,
/// A hashmap mapping type names to pretty-print names.
@@ -296,24 +336,10 @@ pub struct Engine {
/// Optimize the AST after compilation.
pub(crate) optimization_level: OptimizationLevel,
/// Maximum levels of call-stack to prevent infinite recursion.
///
/// Defaults to 16 for debug builds and 128 for non-debug builds.
pub(crate) max_call_stack_depth: usize,
/// Maximum depth of statements/expressions at global level.
pub(crate) max_expr_depth: usize,
/// Maximum depth of statements/expressions in functions.
pub(crate) max_function_expr_depth: usize,
/// Maximum number of operations allowed to run.
pub(crate) max_operations: u64,
/// Maximum number of modules allowed to load.
pub(crate) max_modules: usize,
/// Maximum length of a string.
pub(crate) max_string_size: usize,
/// Maximum length of an array.
pub(crate) max_array_size: usize,
/// Maximum number of properties in a map.
pub(crate) max_map_size: usize,
/// Max limits.
#[cfg(not(feature = "unchecked"))]
pub(crate) limits: Limits,
}
impl fmt::Debug for Engine {
@@ -338,7 +364,8 @@ impl Default for Engine {
#[cfg(not(feature = "no_std"))]
#[cfg(not(target_arch = "wasm32"))]
module_resolver: Some(Box::new(resolvers::FileModuleResolver::new())),
#[cfg(any(feature = "no_module", feature = "no_std", target_arch = "wasm32",))]
#[cfg(not(feature = "no_module"))]
#[cfg(any(feature = "no_std", target_arch = "wasm32",))]
module_resolver: None,
type_names: None,
@@ -360,14 +387,17 @@ impl Default for Engine {
#[cfg(not(feature = "no_optimize"))]
optimization_level: OptimizationLevel::Simple,
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH,
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH,
max_operations: 0,
max_modules: usize::MAX,
max_string_size: 0,
max_array_size: 0,
max_map_size: 0,
#[cfg(not(feature = "unchecked"))]
limits: Limits {
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH,
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH,
max_operations: 0,
max_modules: usize::MAX,
max_string_size: 0,
max_array_size: 0,
max_map_size: 0,
},
};
engine.load_package(StandardPackage::new().get());
@@ -546,6 +576,8 @@ impl Engine {
packages: Default::default(),
global_module: Default::default(),
#[cfg(not(feature = "no_module"))]
module_resolver: None,
type_names: None,
@@ -563,14 +595,17 @@ impl Engine {
#[cfg(not(feature = "no_optimize"))]
optimization_level: OptimizationLevel::Simple,
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH,
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH,
max_operations: 0,
max_modules: usize::MAX,
max_string_size: 0,
max_array_size: 0,
max_map_size: 0,
#[cfg(not(feature = "unchecked"))]
limits: Limits {
max_call_stack_depth: MAX_CALL_STACK_DEPTH,
max_expr_depth: MAX_EXPR_DEPTH,
max_function_expr_depth: MAX_FUNCTION_EXPR_DEPTH,
max_operations: 0,
max_modules: usize::MAX,
max_string_size: 0,
max_array_size: 0,
max_map_size: 0,
},
}
}
@@ -982,23 +1017,25 @@ impl Engine {
fn get_indexed_mut<'a>(
&self,
state: &mut State,
lib: &Module,
_lib: &Module,
target: &'a mut Target,
mut idx: Dynamic,
mut _idx: Dynamic,
idx_pos: Position,
create: bool,
level: usize,
_level: usize,
) -> Result<Target<'a>, Box<EvalAltResult>> {
self.inc_operations(state)?;
#[cfg(not(feature = "no_index"))]
let is_ref = target.is_ref();
let val = target.as_mut();
match val {
#[cfg(not(feature = "no_index"))]
Dynamic(Union::Array(arr)) => {
// val_array[idx]
let index = idx
let index = _idx
.as_int()
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_pos))?;
@@ -1021,13 +1058,13 @@ impl Engine {
Dynamic(Union::Map(map)) => {
// val_map[idx]
Ok(if create {
let index = idx
let index = _idx
.take_immutable_string()
.map_err(|_| EvalAltResult::ErrorStringIndexExpr(idx_pos))?;
map.entry(index).or_insert(Default::default()).into()
} else {
let index = idx
let index = _idx
.downcast_ref::<ImmutableString>()
.ok_or_else(|| EvalAltResult::ErrorStringIndexExpr(idx_pos))?;
@@ -1041,7 +1078,7 @@ impl Engine {
Dynamic(Union::Str(s)) => {
// val_string[idx]
let chars_len = s.chars().count();
let index = idx
let index = _idx
.as_int()
.map_err(|_| EvalAltResult::ErrorNumericIndexExpr(idx_pos))?;
@@ -1062,9 +1099,9 @@ impl Engine {
#[cfg(not(feature = "no_index"))]
_ => {
let type_name = val.type_name();
let args = &mut [val, &mut idx];
let args = &mut [val, &mut _idx];
self.exec_fn_call(
state, lib, FN_IDX_GET, true, 0, args, is_ref, true, None, level,
state, _lib, FN_IDX_GET, true, 0, args, is_ref, true, None, _level,
)
.map(|(v, _)| v.into())
.map_err(|err| match *err {
@@ -1639,19 +1676,20 @@ impl Engine {
Stmt::Const(_) => unreachable!(),
// Import statement
#[cfg(not(feature = "no_module"))]
Stmt::Import(x) => {
let (expr, (name, pos)) = x.as_ref();
let (expr, (name, _pos)) = x.as_ref();
// Guard against too many modules
if state.modules >= self.max_modules {
return Err(Box::new(EvalAltResult::ErrorTooManyModules(*pos)));
#[cfg(not(feature = "unchecked"))]
if state.modules >= self.limits.max_modules {
return Err(Box::new(EvalAltResult::ErrorTooManyModules(*_pos)));
}
if let Some(path) = self
.eval_expr(scope, mods, state, lib, this_ptr, &expr, level)?
.try_cast::<ImmutableString>()
{
#[cfg(not(feature = "no_module"))]
if let Some(resolver) = &self.module_resolver {
let mut module = resolver.resolve(self, &path, expr.position())?;
module.index_all_sub_modules();
@@ -1666,15 +1704,13 @@ impl Engine {
expr.position(),
)))
}
#[cfg(feature = "no_module")]
Ok(Default::default())
} else {
Err(Box::new(EvalAltResult::ErrorImportExpr(expr.position())))
}
}
// Export statement
#[cfg(not(feature = "no_module"))]
Stmt::Export(list) => {
for ((id, id_pos), rename) in list.iter() {
// Mark scope variables as public
@@ -1696,8 +1732,18 @@ impl Engine {
.map_err(|err| err.new_position(stmt.position()))
}
#[cfg(feature = "unchecked")]
#[inline(always)]
fn check_data_size(
&self,
result: Result<Dynamic, Box<EvalAltResult>>,
) -> Result<Dynamic, Box<EvalAltResult>> {
return result;
}
/// Check a result to ensure that the data size is within allowable limit.
/// Position in `EvalAltResult` may be None and should be set afterwards.
#[cfg(not(feature = "unchecked"))]
fn check_data_size(
&self,
result: Result<Dynamic, Box<EvalAltResult>>,
@@ -1706,7 +1752,8 @@ impl Engine {
return result;
// If no data size limits, just return
if self.max_string_size + self.max_array_size + self.max_map_size == 0 {
if self.limits.max_string_size + self.limits.max_array_size + self.limits.max_map_size == 0
{
return result;
}
@@ -1766,37 +1813,37 @@ impl Engine {
// Simply return all errors
Err(_) => return result,
// String with limit
Ok(Dynamic(Union::Str(_))) if self.max_string_size > 0 => (),
Ok(Dynamic(Union::Str(_))) if self.limits.max_string_size > 0 => (),
// Array with limit
#[cfg(not(feature = "no_index"))]
Ok(Dynamic(Union::Array(_))) if self.max_array_size > 0 => (),
Ok(Dynamic(Union::Array(_))) if self.limits.max_array_size > 0 => (),
// Map with limit
#[cfg(not(feature = "no_object"))]
Ok(Dynamic(Union::Map(_))) if self.max_map_size > 0 => (),
Ok(Dynamic(Union::Map(_))) if self.limits.max_map_size > 0 => (),
// Everything else is simply returned
Ok(_) => return result,
};
let (arr, map, s) = calc_size(result.as_ref().unwrap());
if s > self.max_string_size {
if s > self.limits.max_string_size {
Err(Box::new(EvalAltResult::ErrorDataTooLarge(
"Length of string".to_string(),
self.max_string_size,
self.limits.max_string_size,
s,
Position::none(),
)))
} else if arr > self.max_array_size {
} else if arr > self.limits.max_array_size {
Err(Box::new(EvalAltResult::ErrorDataTooLarge(
"Size of array".to_string(),
self.max_array_size,
self.limits.max_array_size,
arr,
Position::none(),
)))
} else if map > self.max_map_size {
} else if map > self.limits.max_map_size {
Err(Box::new(EvalAltResult::ErrorDataTooLarge(
"Number of properties in object map".to_string(),
self.max_map_size,
self.limits.max_map_size,
map,
Position::none(),
)))
@@ -1812,7 +1859,7 @@ impl Engine {
#[cfg(not(feature = "unchecked"))]
// Guard against too many operations
if self.max_operations > 0 && state.operations > self.max_operations {
if self.limits.max_operations > 0 && state.operations > self.limits.max_operations {
return Err(Box::new(EvalAltResult::ErrorTooManyOperations(
Position::none(),
)));