Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fixes. #818

Merged
merged 19 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Fixes to bugs found via fuzzing
* Fixed improper parsing of numbers with too many decimal points.
* Fixed exponential running time when raising a decimal number to a very large power (> 1 million) -- it now returns an overflow error.
* Shared values that contain reference loops no longer cause a stack overflow when printing.
* `sleep` no longer panics on `NaN`.
* `switch` on ranges now work properly.

Other bug fixes
---------------
Expand All @@ -47,7 +49,11 @@ Other bug fixes
New features
------------

* `#[derive(CustomType)]` is now available, driven by procedural macros in `rhai_codegen`.
* A new `FuncRegistration` API is added to assist in registering native Rust functions into modules with various settings. Some of the original `Module::set_fn...` API is now deprecated.
* Functions defined in plugin modules can now be marked as `volatile` which prevents it from being optimized away even under `OptimizationLevel::Full`.
* Added `Engine::max_functions` and `Engine::set_max_functions` to limit the maximum number of functions allowed in a script. This s to guard against DOS attacks -- e.g. a simple closure `||` (two characters) is a function. When `max_function` is exceeded during script compilation, a new parse error, `TooManyFunctions`, is returned.
* `Engine::get_interned_string` is made public instead of gated under `internals`.

Enhancements
------------
Expand All @@ -57,6 +63,7 @@ Enhancements
* `Token::FloatConstant` and `Token::DecimalConstant` now carry the original text representation for use in, say, a _token mapper_.
* `Dynamic::is_fnptr` is made a public API.
* `Scope::get_value_ref` and `Scope::get_value_mut` are added.
* `TypeBuilder::with_name` now takes any `&str` instead of just `&'static str`.


Version 1.16.3
Expand Down
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ num-traits = { version = "0.2.0", default-features = false }
once_cell = { version = "1.7.0", default-features = false, features = ["race"] }
bitflags = { version = "2.0.0", default-features = false }
smartstring = { version = "1.0.0", default-features = false }
rhai_codegen = { version = "1.7.0", path = "codegen" }
rhai_codegen = { version = "1.17.0", path = "codegen" }

no-std-compat = { git = "https://gitlab.com/jD91mZM2/no-std-compat", version = "0.4.1", default-features = false, features = ["alloc"], optional = true }
libm = { version = "0.2.0", default-features = false, optional = true }
Expand Down Expand Up @@ -165,3 +165,6 @@ features = ["document-features", "metadata", "serde", "internals", "decimal", "d
# Notice that a custom modified version of `rustyline` is used which supports bracketed paste on Windows.
# This can be moved to the official version when bracketed paste is added.
rustyline = { git = "https://github.com/schungx/rustyline", branch = "v13" }

# Patch SmartString to resolve an UB issue.
smartstring = { git = "https://github.com/bodil/smartstring", ref = "refs/pull/34/head" }
2 changes: 1 addition & 1 deletion codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rhai_codegen"
version = "1.7.0"
version = "1.17.0"
edition = "2018"
resolver = "2"
authors = ["jhwgh1968", "Stephen Chung"]
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/custom_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn derive_custom_type_impl(input: DeriveInput) -> TokenStream {

quote! {
impl ::rhai::CustomType for #name {
fn build(mut builder: ::rhai::TypeBuilder<'_, Self>) {
fn build(mut builder: ::rhai::TypeBuilder<Self>) {
#accessors;
}
}
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ impl ExportedFn {
#[inline(always)] pub fn param_types() -> [TypeId; #arg_count] { [#(#input_type_exprs),*] }
}
#(#cfg_attrs)*
impl PluginFunction for #type_name {
impl PluginFunc for #type_name {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
#(#unpack_statements)*
Expand Down
46 changes: 22 additions & 24 deletions codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,19 +345,18 @@ pub fn set_exported_fn(args: proc_macro::TokenStream) -> proc_macro::TokenStream
Ok((module_expr, export_name, rust_mod_path)) => {
let gen_mod_path = crate::register::generated_module_path(&rust_mod_path);

#[cfg(feature = "metadata")]
let param_names = quote! {
Some(#gen_mod_path::Token::PARAM_NAMES)
let mut tokens = quote! {
let fx = FuncRegistration::new(#export_name).with_namespace(FnNamespace::Internal)
};
#[cfg(not(feature = "metadata"))]
let param_names = quote! { None };

proc_macro::TokenStream::from(quote! {
#module_expr.set_fn(#export_name, FnNamespace::Internal, FnAccess::Public,
#param_names,
&#gen_mod_path::Token::param_types(),
#gen_mod_path::Token().into())
})
#[cfg(feature = "metadata")]
tokens.extend(quote! {
.with_params_info(#gen_mod_path::Token::PARAM_NAMES)
});
tokens.extend(quote! {
;
#module_expr.set_fn_raw_with_options(fx, &#gen_mod_path::Token::param_types(), #gen_mod_path::Token().into());
});
tokens.into()
}
Err(e) => e.to_compile_error().into(),
}
Expand Down Expand Up @@ -394,19 +393,18 @@ pub fn set_exported_global_fn(args: proc_macro::TokenStream) -> proc_macro::Toke
Ok((module_expr, export_name, rust_mod_path)) => {
let gen_mod_path = crate::register::generated_module_path(&rust_mod_path);

#[cfg(feature = "metadata")]
let param_names = quote! {
Some(#gen_mod_path::Token::PARAM_NAMES)
let mut tokens = quote! {
let fx = FuncRegistration::new(#export_name).with_namespace(FnNamespace::Global)
};
#[cfg(not(feature = "metadata"))]
let param_names = quote! { None };

proc_macro::TokenStream::from(quote! {
#module_expr.set_fn(#export_name, FnNamespace::Global, FnAccess::Public,
#param_names,
&#gen_mod_path::Token::param_types(),
#gen_mod_path::Token().into())
})
#[cfg(feature = "metadata")]
tokens.extend(quote! {
.with_params_info(#gen_mod_path::Token::PARAM_NAMES)
});
tokens.extend(quote! {
;
#module_expr.set_fn_raw_with_options(fx, &#gen_mod_path::Token::param_types(), #gen_mod_path::Token().into());
});
tokens.into()
}
Err(e) => e.to_compile_error().into(),
}
Expand Down
92 changes: 24 additions & 68 deletions codegen/src/rhai_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::collections::BTreeMap;

use crate::attrs::ExportScope;
use crate::function::{
flatten_type_groups, print_type, ExportedFn, FnNamespaceAccess, FnSpecialAccess, FN_GET,
FN_IDX_GET, FN_IDX_SET, FN_SET,
print_type, ExportedFn, FnNamespaceAccess, FnSpecialAccess, FN_GET, FN_IDX_GET, FN_IDX_SET,
FN_SET,
};
use crate::module::Module;

Expand Down Expand Up @@ -39,8 +39,6 @@ pub fn generate_body(
let mut set_const_statements = Vec::new();
let mut add_mod_blocks = Vec::new();
let mut set_flattened_mod_blocks = Vec::new();
let str_type_path = syn::parse2::<syn::Path>(quote! { str }).unwrap();
let string_type_path = syn::parse2::<syn::Path>(quote! { String }).unwrap();

for ExportedConst {
name: const_name,
Expand Down Expand Up @@ -146,49 +144,6 @@ pub fn generate_body(
);
let reg_names = function.exported_names();

let fn_input_types: Vec<_> = function
.arg_list()
.map(|fn_arg| match fn_arg {
syn::FnArg::Receiver(..) => unreachable!("receiver fn outside impl!?"),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => {
let arg_type = match flatten_type_groups(ty.as_ref()) {
syn::Type::Reference(syn::TypeReference {
mutability: None,
ref elem,
..
}) => match flatten_type_groups(elem.as_ref()) {
syn::Type::Path(ref p) if p.path == str_type_path => {
syn::parse2::<syn::Type>(quote! {
ImmutableString })
.unwrap()
}
_ => unreachable!("non-string shared reference!?"),
},
syn::Type::Path(ref p) if p.path == string_type_path => {
syn::parse2::<syn::Type>(quote! {
ImmutableString })
.unwrap()
}
syn::Type::Reference(syn::TypeReference {
mutability: Some(_),
ref elem,
..
}) => match flatten_type_groups(elem.as_ref()) {
syn::Type::Path(ref p) => syn::parse2::<syn::Type>(quote! {
#p })
.unwrap(),
_ => unreachable!("invalid mutable reference!?"),
},
t => t.clone(),
};

syn::parse2::<syn::Expr>(quote! {
TypeId::of::<#arg_type>()})
.unwrap()
}
})
.collect();

let cfg_attrs: Vec<_> = function
.cfg_attrs()
.iter()
Expand Down Expand Up @@ -226,33 +181,34 @@ pub fn generate_body(
fn_literal.span(),
);

let mut tokens = quote! {
#(#cfg_attrs)*
FuncRegistration::new(#fn_literal).with_namespace(FnNamespace::#ns_str)
};
#[cfg(feature = "metadata")]
let (param_names, comments) = (
quote! { Some(#fn_token_name::PARAM_NAMES) },
function
{
tokens.extend(quote! {
.with_params_info(#fn_token_name::PARAM_NAMES)
});

let comments = function
.comments()
.iter()
.map(|s| syn::LitStr::new(s, Span::call_site()))
.collect::<Vec<_>>(),
);
#[cfg(not(feature = "metadata"))]
let (param_names, comments) = (quote! { None }, Vec::<syn::LitStr>::new());
.collect::<Vec<_>>();

set_fn_statements.push(if comments.is_empty() {
syn::parse2::<syn::Stmt>(quote! {
#(#cfg_attrs)*
m.set_fn(#fn_literal, FnNamespace::#ns_str, FnAccess::Public,
#param_names, &[#(#fn_input_types),*], #fn_token_name().into());
})
.unwrap()
} else {
syn::parse2::<syn::Stmt>(quote! {
#(#cfg_attrs)*
m.set_fn_with_comments(#fn_literal, FnNamespace::#ns_str, FnAccess::Public,
#param_names, &[#(#fn_input_types),*], &[#(#comments),*], #fn_token_name().into());
})
.unwrap()
if !comments.is_empty() {
tokens.extend(quote! {
.with_comments(&[#(#comments),*])
});
}
}

tokens.extend(quote! {
.set_into_module_raw(m, &#fn_token_name::param_types(), #fn_token_name().into());
});

set_fn_statements.push(syn::parse2::<syn::Stmt>(tokens).unwrap());
}

gen_fn_tokens.push(quote! {
Expand Down
16 changes: 8 additions & 8 deletions codegen/src/test/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["()"];
#[inline(always)] pub fn param_types() -> [TypeId; 0usize] { [] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)] fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
Ok(Dynamic::from(do_nothing()))
}
Expand Down Expand Up @@ -318,7 +318,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["x: usize", "()"];
#[inline(always)] pub fn param_types() -> [TypeId; 1usize] { [TypeId::of::<usize>()] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg0 = mem::take(args[0usize]).cast::<usize>();
Expand Down Expand Up @@ -359,7 +359,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["x: usize", "()"];
#[inline(always)] pub fn param_types() -> [TypeId; 1usize] { [TypeId::of::<usize>()] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg0 = mem::take(args[0usize]).cast::<usize>();
Expand Down Expand Up @@ -403,7 +403,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["rhai::Dynamic"];
#[inline(always)] pub fn param_types() -> [TypeId; 0usize] { [] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
Ok(Dynamic::from(return_dynamic()))
Expand Down Expand Up @@ -438,7 +438,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["x: usize", "()"];
#[inline(always)] pub fn param_types() -> [TypeId; 1usize] { [TypeId::of::<usize>()] }
}
impl PluginFunction for TestStruct {
impl PluginFunc for TestStruct {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg0 = mem::take(args[0usize]).cast::<usize>();
Expand Down Expand Up @@ -473,7 +473,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["x: usize", "y: usize", "usize"];
#[inline(always)] pub fn param_types() -> [TypeId; 2usize] { [TypeId::of::<usize>(), TypeId::of::<usize>()] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg0 = mem::take(args[0usize]).cast::<usize>();
Expand Down Expand Up @@ -515,7 +515,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["x: &mut usize", "y: usize", "()"];
#[inline(always)] pub fn param_types() -> [TypeId; 2usize] { [TypeId::of::<usize>(), TypeId::of::<usize>()] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg1 = mem::take(args[1usize]).cast::<usize>();
Expand Down Expand Up @@ -558,7 +558,7 @@ mod generate_tests {
pub const PARAM_NAMES: &'static [&'static str] = &["message: &str", "()"];
#[inline(always)] pub fn param_types() -> [TypeId; 1usize] { [TypeId::of::<ImmutableString>()] }
}
impl PluginFunction for Token {
impl PluginFunc for Token {
#[inline(always)]
fn call(&self, context: Option<NativeCallContext>, args: &mut [&mut Dynamic]) -> RhaiResult {
let arg0 = mem::take(args[0usize]).into_immutable_string().unwrap();
Expand Down
Loading
Loading