C++: fix crash when accessing empty model from Slint

Fixes #3704
This commit is contained in:
Olivier Goffart 2023-10-19 16:44:42 +02:00 committed by Olivier Goffart
parent 403bb6c716
commit 172dcfa775
4 changed files with 17 additions and 3 deletions

View file

@ -34,6 +34,7 @@ All notable changes to this project are documented in this file.
- Removed the need for C++ exceptions in generated code.
- Added ability to only build the Slint compiler or use an external compiler.
- ESP-IDF: wait for vsync before swapping frame buffers.
- Fixed crash when accessing empty model from Slint
### LSP

View file

@ -341,13 +341,25 @@ using ModelPeer = std::weak_ptr<ModelChangeListener>;
template<typename M>
auto access_array_index(const M &model, size_t index)
{
if (const auto v = model->row_data_tracked(index)) {
if (!model) {
return decltype(*model->row_data_tracked(index)) {};
} else if (const auto v = model->row_data_tracked(index)) {
return *v;
} else {
return decltype(*v) {};
}
}
template<typename M>
long int model_length(const M &model) {
if (!model) {
return 0;
} else {
model->track_row_count_changes();
return model->row_count();
}
}
} // namespace private_api
/// \rst

View file

@ -3035,8 +3035,7 @@ fn compile_builtin_function_call(
format!("{}.size()", a.next().unwrap())
}
BuiltinFunction::ArrayLength => {
// note: cast to "long" to avoid signed vs signed comparison warning, because all other integers coming from slint are signed
format!("[](const auto &model){{ (*model).track_row_count_changes(); return long((*model).row_count()); }}({})", a.next().unwrap())
format!("slint::private_api::model_length({})", a.next().unwrap())
}
BuiltinFunction::Rgb => {
format!("slint::Color::from_argb_uint8(std::clamp(static_cast<float>({a}) * 255., 0., 255.), std::clamp(static_cast<int>({r}), 0, 255), std::clamp(static_cast<int>({g}), 0, 255), std::clamp(static_cast<int>({b}), 0, 255))",

View file

@ -24,6 +24,7 @@ const TestCase &instance = *handle;
assert_eq(instance.get_num_ints(), 5);
assert_eq(instance.get_n(), 4);
assert_eq(instance.get_third_int(), 3);
assert_eq(instance.get_test(), true);
auto model = std::make_shared<slint::VectorModel<int>>(std::vector<int>{1, 2, 3, 4, 5, 6, 7});
instance.set_ints(model);
@ -45,6 +46,7 @@ let instance = TestCase::new().unwrap();
assert_eq!(instance.get_num_ints(), 5);
assert_eq!(instance.get_n(), 4);
assert_eq!(instance.get_third_int(), 3);
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());
instance.set_ints(slint::ModelRc::from(model.clone()));