Skip to content

Commit

Permalink
Merge pull request #780 from schungx/master
Browse files Browse the repository at this point in the history
Fix crash.
  • Loading branch information
schungx committed Nov 12, 2023
2 parents 3b31c61 + 18a09ea commit a346a86
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 27 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ Potentially breaking changes
* `EvalContext::new`, `FloatWrapper` and `ConditionalExpr` are now exported only under `internals`.
* `AST::clear_doc` is removed.

Bug fixes
----------

* Fixed crash when parsing multi-segment interpolated string longer than maximum.

Deprecated API's
----------------

Expand All @@ -23,12 +28,12 @@ Enhancements
* Added `to_int` method for characters.
* `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.

Version 1.16.3
==============

Public fields of `VarDefInfo` is marked deprecated but still accessible.
Public fields of `VarDefInfo` are marked deprecated but still accessible.


Version 1.16.2
Expand Down
4 changes: 0 additions & 4 deletions no_std/no_std_test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,3 @@ inherits = "release"
[profile.macos]
inherits = "release"
lto = "fat"

# `ahash` has a problem preventing `no-std` builds. Use this PR until it is fixed.
[patch.crates-io]
const-random = { git = "https://github.com/tkaitchuck/constrandom", rev = "refs/pull/31/head" }
2 changes: 1 addition & 1 deletion src/eval/chaining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use std::prelude::v1::*;
static INDEXER_HASHES: OnceCell<(u64, u64)> = OnceCell::new();

/// Get the pre-calculated index getter/setter hashes.
#[inline(always)]
#[inline]
#[must_use]
fn hash_idx() -> (u64, u64) {
*INDEXER_HASHES.get_or_init(|| {
Expand Down
11 changes: 6 additions & 5 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1589,11 +1589,12 @@ impl Engine {
.push(Expr::StringConstant(state.get_interned_string(*s), pos));
}
}
(Token::LexError(err), pos)
if matches!(*err, LexError::UnterminatedString) =>
{
return Err(err.into_err(pos))
}
(Token::LexError(err), pos) => match *err {
LexError::UnterminatedString | LexError::StringTooLong(_) => {
return Err(err.into_err(pos))
}
_ => unreachable!("improper lex error: {:?}", err),
},
(token, ..) => unreachable!(
"string within an interpolated string literal expected but gets {:?}",
token
Expand Down
4 changes: 2 additions & 2 deletions src/types/dynamic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1480,7 +1480,7 @@ impl Dynamic {
/// Get a reference of a specific type to the [`Dynamic`].
/// Casting to [`Dynamic`] just returns a reference to it.
///
/// Returns [`None`] if the cast fails, or if the value is shared.
/// Returns [`None`] if the cast fails, or if the value is _shared_.
#[inline]
#[must_use]
pub(crate) fn downcast_ref<T: Any + Clone + ?Sized>(&self) -> Option<&T> {
Expand Down Expand Up @@ -1578,7 +1578,7 @@ impl Dynamic {
/// Get a mutable reference of a specific type to the [`Dynamic`].
/// Casting to [`Dynamic`] just returns a mutable reference to it.
///
/// Returns [`None`] if the cast fails, or if the value is shared.
/// Returns [`None`] if the cast fails, or if the value is _shared_.
#[inline]
#[must_use]
pub(crate) fn downcast_mut<T: Any + Clone + ?Sized>(&mut self) -> Option<&mut T> {
Expand Down
89 changes: 76 additions & 13 deletions src/types/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,15 +484,8 @@ impl Scope<'_> {
self.names
.iter()
.rev() // Always search a Scope in reverse order
.enumerate()
.find_map(|(i, key)| {
if name == key {
let index = len - 1 - i;
Some(index)
} else {
None
}
})
.position(|key| name == key)
.map(|i| len - 1 - i)
}
/// Get the value of an entry in the [`Scope`], starting from the last.
///
Expand All @@ -514,10 +507,80 @@ impl Scope<'_> {
self.names
.iter()
.rev()
.enumerate()
.find(|(.., key)| &name == key)
.map(|(index, ..)| self.values[len - 1 - index].flatten_clone())
.and_then(Dynamic::try_cast)
.position(|key| &name == key)
.and_then(|i| self.values[len - 1 - i].flatten_clone().try_cast())
}
/// Get a reference the value of an entry in the [`Scope`], starting from the last.
///
/// # Panics
///
/// Panics if the value is _shared_.
///
/// # Example
///
/// ```
/// use rhai::Scope;
///
/// let mut my_scope = Scope::new();
///
/// my_scope.push("x", 42_i64);
///
/// let ptr = my_scope.get_value_ref::<i64>("x").expect("x should exist");
///
/// assert_eq!(*ptr, 42);
/// ```
#[inline]
#[must_use]
pub fn get_value_ref<T: Variant + Clone>(&self, name: &str) -> Option<&T> {
let len = self.len();

self.names
.iter()
.rev()
.position(|key| &name == key)
.and_then(|i| {
let v = &self.values[len - 1 - i];
#[cfg(not(feature = "no_closure"))]
assert!(!v.is_shared());
v.downcast_ref()
})
}
/// Get a mutable reference the value of an entry in the [`Scope`], starting from the last.
///
/// # Panics
///
/// Panics if the value is _shared_.
///
/// # Example
///
/// ```
/// use rhai::Scope;
///
/// let mut my_scope = Scope::new();
///
/// my_scope.push("x", 42_i64);
///
/// let ptr = my_scope.get_value_mut::<i64>("x").expect("x should exist");
///
/// *ptr = 0;
///
/// assert_eq!(my_scope.get_value::<i64>("x").expect("x should exist"), 0);
/// ```
#[inline]
#[must_use]
pub fn get_value_mut<T: Variant + Clone>(&mut self, name: &str) -> Option<&mut T> {
let len = self.len();

self.names
.iter_mut()
.rev()
.position(|key| &name == key)
.and_then(move |i| {
let v = &mut self.values[len - 1 - i];
#[cfg(not(feature = "no_closure"))]
assert!(!v.is_shared());
v.downcast_mut()
})
}
/// Check if the named entry in the [`Scope`] is constant.
///
Expand Down
4 changes: 4 additions & 0 deletions tests/data_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ fn test_max_string_size() {

assert_eq!(*engine.compile(r#"let x = "朝に紅顔、暮に白骨";"#).unwrap_err().err_type(), ParseErrorType::LiteralTooLarge("Length of string".to_string(), 10));

assert_eq!(*engine.compile("let x = `朝に紅顔、暮に白骨`;").unwrap_err().err_type(), ParseErrorType::LiteralTooLarge("Length of string".to_string(), 10));

assert_eq!(*engine.compile(r#"let x = `Say ${"Hi!"} and so be it.`;"#).unwrap_err().err_type(), ParseErrorType::LiteralTooLarge("Length of string".to_string(), 10));

assert!(matches!(
*engine
.run(
Expand Down

0 comments on commit a346a86

Please sign in to comment.