mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
Fix array index access at negative index
Conversion from negative float to unsigned is saturating to 0 in rust and undefined behavior in C++, we should therefore handle the case properly Fixes #8222
This commit is contained in:
parent
ff6065ace4
commit
cd8ab8ce53
6 changed files with 24 additions and 10 deletions
|
@ -25,9 +25,9 @@ struct ModelChangeListener
|
|||
using ModelPeer = std::weak_ptr<ModelChangeListener>;
|
||||
|
||||
template<typename M>
|
||||
auto access_array_index(const std::shared_ptr<M> &model, size_t index)
|
||||
auto access_array_index(const std::shared_ptr<M> &model, std::ptrdiff_t index)
|
||||
{
|
||||
if (!model) {
|
||||
if (!model || index < 0) {
|
||||
return decltype(*model->row_data_tracked(index)) {};
|
||||
} else if (const auto v = model->row_data_tracked(index)) {
|
||||
return *v;
|
||||
|
|
|
@ -3250,9 +3250,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
|
|||
let base_e = compile_expression(array, ctx);
|
||||
let index_e = compile_expression(index, ctx);
|
||||
let value_e = compile_expression(value, ctx);
|
||||
format!(
|
||||
"{base_e}->set_row_data({index_e}, {value_e})"
|
||||
)
|
||||
format!("[&](auto index, const auto &base) {{ if (index >= 0. && std::size_t(index) < base->row_count()) base->set_row_data(index, {value_e}); }}({index_e}, {base_e})")
|
||||
}
|
||||
Expression::BinaryExpression { lhs, rhs, op } => {
|
||||
let lhs_str = compile_expression(lhs, ctx);
|
||||
|
|
|
@ -2381,7 +2381,7 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
|
|||
let base_e = compile_expression(array, ctx);
|
||||
let index_e = compile_expression(index, ctx);
|
||||
let value_e = compile_expression(value, ctx);
|
||||
quote!((#base_e).set_row_data(#index_e as usize, #value_e as _))
|
||||
quote!((#base_e).set_row_data(#index_e as isize as usize, #value_e as _))
|
||||
}
|
||||
Expression::BinaryExpression { lhs, rhs, op } => {
|
||||
let lhs_ty = lhs.ty(ctx);
|
||||
|
|
|
@ -173,7 +173,7 @@ pub fn eval_expression(expression: &Expression, local_context: &mut EvalLocalCon
|
|||
let index = eval_expression(index, local_context);
|
||||
match (array, index) {
|
||||
(Value::Model(model), Value::Number(index)) => {
|
||||
model.row_data_tracked(index as usize).unwrap_or_else(|| default_value_for_type(&expression.ty()))
|
||||
model.row_data_tracked(index as isize as usize).unwrap_or_else(|| default_value_for_type(&expression.ty()))
|
||||
}
|
||||
_ => {
|
||||
Value::Void
|
||||
|
@ -1472,8 +1472,8 @@ fn eval_assignment(lhs: &Expression, op: char, rhs: Value, local_context: &mut E
|
|||
let index = eval_expression(index, local_context);
|
||||
match (array, index) {
|
||||
(Value::Model(model), Value::Number(index)) => {
|
||||
let index = index as usize;
|
||||
if (index) < model.row_count() {
|
||||
if index >= 0. && (index as usize) < model.row_count() {
|
||||
let index = index as usize;
|
||||
if op == '=' {
|
||||
model.set_row_data(index, rhs);
|
||||
} else {
|
||||
|
|
|
@ -13,9 +13,11 @@ export component TestCase {
|
|||
|
||||
out property<bool> test: num_ints == 5 && operations == 10
|
||||
&& hello_world == (["", "world"])[1] && empty_model.length == 0 && empty_model[45].a.length == 0
|
||||
&& array_of_array[1][1] == 2 && [].length == 0 && ninth_int == 0;
|
||||
&& array_of_array[1][1] == 2 && [].length == 0 && ninth_int == 0 && minus_int == 0 && decimal_check;
|
||||
out property<int> third_int: ints[2];
|
||||
out property<int> ninth_int: ints[8];
|
||||
out property<int> minus_int: ints[-1];
|
||||
out property<bool> decimal_check: ints[-0.5] == 1 && ints[2.9] == 3 && ints[-1.3] == 0;
|
||||
out property<string> hello_world: [{t: "hello"}, {t: "world"}][1].t;
|
||||
|
||||
for xxx in (third_int == 0) ? ints : [] : Rectangle {}
|
||||
|
@ -30,6 +32,7 @@ assert_eq(instance.get_num_ints(), 5);
|
|||
assert_eq(instance.get_n(), 4);
|
||||
assert_eq(instance.get_third_int(), 3);
|
||||
assert_eq(instance.get_ninth_int(), 0);
|
||||
assert_eq(instance.get_minus_int(), 0);
|
||||
assert_eq(instance.get_test(), true);
|
||||
|
||||
auto model = std::make_shared<slint::VectorModel<int>>(std::vector<int>{1, 2, 3, 4, 5, 6, 7});
|
||||
|
@ -41,6 +44,7 @@ assert_eq(instance.get_num_ints(), 8);
|
|||
model->set_row_data(2, 100);
|
||||
assert_eq(instance.get_third_int(), 100);
|
||||
assert_eq(instance.get_ninth_int(), 0);
|
||||
assert_eq(instance.get_minus_int(), 0);
|
||||
|
||||
model->push_back(9);
|
||||
assert_eq(instance.get_ninth_int(), 9);
|
||||
|
@ -58,6 +62,7 @@ assert_eq!(instance.get_num_ints(), 5);
|
|||
assert_eq!(instance.get_n(), 4);
|
||||
assert_eq!(instance.get_third_int(), 3);
|
||||
assert_eq!(instance.get_ninth_int(), 0);
|
||||
assert_eq!(instance.get_minus_int(), 0);
|
||||
assert_eq!(instance.get_test(), true);
|
||||
|
||||
let model: std::rc::Rc<slint::VecModel<i32>> = std::rc::Rc::new(vec![1, 2, 3, 4, 5, 6, 7].into());
|
||||
|
@ -69,6 +74,7 @@ assert_eq!(instance.get_num_ints(), 8);
|
|||
model.set_row_data(2, 100);
|
||||
assert_eq!(instance.get_third_int(), 100);
|
||||
assert_eq!(instance.get_ninth_int(), 0);
|
||||
assert_eq!(instance.get_minus_int(), 0);
|
||||
|
||||
model.push(9);
|
||||
assert_eq!(instance.get_ninth_int(), 9);
|
||||
|
@ -84,6 +90,8 @@ assert.equal(instance.num_ints, 5);
|
|||
assert.equal(instance.n, 4);
|
||||
assert.equal(instance.third_int, 3);
|
||||
assert.equal(instance.ninth_int, 0);
|
||||
assert.equal(instance.minus_int, 0);
|
||||
assert(instance.test);
|
||||
|
||||
let model = new slintlib.ArrayModel([1, 2, 3, 4, 5, 6, 7]);
|
||||
instance.ints = model;
|
||||
|
@ -94,6 +102,7 @@ assert.equal(instance.num_ints, 8);
|
|||
model.setRowData(2, 100);
|
||||
assert.equal(instance.third_int, 100);
|
||||
assert.equal(instance.ninth_int, 0);
|
||||
assert.equal(instance.minus_int, 0);
|
||||
|
||||
model.push(9);
|
||||
assert.equal(instance.ninth_int, 9);
|
||||
|
|
|
@ -17,6 +17,13 @@ TestCase := Rectangle {
|
|||
if (first != 1) { return false; }
|
||||
bar[0] = 42;
|
||||
if (first != 42) { return false; }
|
||||
bar[-1] = 18;
|
||||
bar[3] = 89;
|
||||
bar[-30.5] = 78;
|
||||
bar[1.1] = 7552;
|
||||
if (first != 42) { debug(first, "!= 42"); return false; }
|
||||
bar[0.999] = 8;
|
||||
if (first != 8) { debug(first, "!= 8"); return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue