Skip to content

Commit 7c59555

Browse files
committed
Fix integer overflow
1 parent cffc855 commit 7c59555

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Rhai Release Notes
22
==================
33

4+
Version 1.22.0
5+
==============
6+
7+
Bug fixes
8+
---------
9+
10+
* (Fuzzing) An integer-overflow bug from an inclusive range in `get_bits` is fixed.
11+
12+
413
Version 1.21.0
514
==============
615

src/packages/bit_field.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::eval::calc_index;
22
use crate::plugin::*;
33
use crate::{
44
def_package, ExclusiveRange, InclusiveRange, Position, RhaiResultOf, ERR, INT, INT_BITS,
5-
UNSIGNED_INT,
5+
MAX_USIZE_INT, UNSIGNED_INT,
66
};
77
#[cfg(feature = "no_std")]
88
use std::prelude::v1::*;
@@ -106,6 +106,12 @@ mod bit_field_functions {
106106
pub fn get_bits_range_inclusive(value: INT, range: InclusiveRange) -> RhaiResultOf<INT> {
107107
let from = INT::max(*range.start(), 0);
108108
let to = INT::max(*range.end(), from - 1);
109+
110+
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
111+
if to > MAX_USIZE_INT || (to as usize) >= INT_BITS {
112+
return Err(ERR::ErrorBitFieldBounds(INT_BITS, to, Position::NONE).into());
113+
}
114+
109115
get_bits(value, from, to - from + 1)
110116
}
111117
/// Return a portion of bits in the number as a new number.
@@ -126,6 +132,11 @@ mod bit_field_functions {
126132
if bits <= 0 {
127133
return Ok(0);
128134
}
135+
let bits = if bits > MAX_USIZE_INT {
136+
MAX_USIZE_INT
137+
} else {
138+
bits
139+
};
129140

130141
let bit = calc_index(INT_BITS, start, true, || {
131142
ERR::ErrorBitFieldBounds(INT_BITS, start, Position::NONE).into()

tests/get_set.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,12 @@ fn test_get_set_chain_without_write_back() {
163163

164164
engine
165165
.register_type::<Inner>()
166-
.register_get_set("value", |t: &mut Inner| t.value, |_: NativeCallContext, _: &mut Inner, new: INT| panic!("Inner::value setter called with {}", new))
166+
.register_get_set("value", |t: &mut Inner| t.value, |_: NativeCallContext, _: &mut Inner, new: INT| -> () { panic!("Inner::value setter called with {}", new) })
167167
.register_type::<Outer>()
168-
.register_get_set("inner", |_: NativeCallContext, t: &mut Outer| t.inner.clone(), |_: &mut Outer, new: Inner| panic!("Outer::inner setter called with {:?}", new));
168+
.register_get_set("inner", |_: NativeCallContext, t: &mut Outer| t.inner.clone(), |_: &mut Outer, new: Inner| -> () { panic!("Outer::inner setter called with {:?}", new) });
169169

170170
#[cfg(not(feature = "no_index"))]
171-
engine.register_indexer_get_set(|t: &mut Outer, n: INT| Inner { value: t.inner.value * n }, |_: &mut Outer, n: INT, new: Inner| panic!("Outer::inner index setter called with {} and {:?}", n, new));
171+
engine.register_indexer_get_set(|t: &mut Outer, n: INT| Inner { value: t.inner.value * n }, |_: &mut Outer, n: INT, new: Inner| -> () { panic!("Outer::inner index setter called with {} and {:?}", n, new) });
172172

173173
assert_eq!(engine.eval_with_scope::<INT>(&mut scope, "outer.inner.value").unwrap(), 42);
174174

0 commit comments

Comments
 (0)