Skip to content

Commit

Permalink
Fix runtime panic with colpan or rowspan set to zero
Browse files Browse the repository at this point in the history
Make it a compiler error instead:
Fix panic:
```
panicked at internal/core/layout.rs:459:33:
index out of bounds: the len is 2 but the index is 2
```

ChangeLog: Transformed runtime panic with `colspan:0` or `rowspan:0` into a compile error
  • Loading branch information
ogoffart committed Jan 15, 2025
1 parent 22ad614 commit c7f8bb9
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
23 changes: 11 additions & 12 deletions internal/compiler/passes/lower_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,18 @@ impl GridLayout {
layout_cache_prop_v: &NamedReference,
diag: &mut BuildDiagnostics,
) {
let mut get_const_value = |name: &str| {
item_element
.borrow_mut()
.bindings
.remove(name)
.and_then(|e| eval_const_expr(&e.borrow().expression, name, &*e.borrow(), diag))
let mut get_const_value = |name: &str, min| {
item_element.borrow_mut().bindings.remove(name).and_then(|e| {
eval_const_expr(&e.borrow().expression, name, min, &*e.borrow(), diag)
})
};
let colspan = get_const_value("colspan").unwrap_or(1);
let rowspan = get_const_value("rowspan").unwrap_or(1);
if let Some(r) = get_const_value("row") {
let colspan = get_const_value("colspan", 1.).unwrap_or(1);
let rowspan = get_const_value("rowspan", 1.).unwrap_or(1);
if let Some(r) = get_const_value("row", 0.) {
*row = r;
*col = 0;
}
if let Some(c) = get_const_value("col") {
if let Some(c) = get_const_value("col", 0.) {
*col = c;
}

Expand Down Expand Up @@ -776,19 +774,20 @@ fn set_prop_from_cache(
fn eval_const_expr(
expression: &Expression,
name: &str,
min: f64,
span: &dyn crate::diagnostics::Spanned,
diag: &mut BuildDiagnostics,
) -> Option<u16> {
match expression {
Expression::NumberLiteral(v, Unit::None) => {
if *v < 0. || *v > u16::MAX as f64 || !v.trunc().approx_eq(v) {
if *v < min || *v > u16::MAX as f64 || !v.trunc().approx_eq(v) {
diag.push_error(format!("'{}' must be a positive integer", name), span);
None
} else {
Some(*v as u16)
}
}
Expression::Cast { from, .. } => eval_const_expr(from, name, span, diag),
Expression::Cast { from, .. } => eval_const_expr(from, name, min, span, diag),
_ => {
diag.push_error(format!("'{}' must be an integer literal", name), span);
None
Expand Down
8 changes: 8 additions & 0 deletions internal/compiler/tests/syntax/basic/layout2.slint
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export X := Rectangle {
Rectangle { row: 3; }
// ^error{row used outside of a GridLayout}
}

Rectangle {
// This would cause panic at runtime
rowspan: 0;
// ^error{'rowspan' must be a positive integer}
colspan: 0;
// ^error{'colspan' must be a positive integer}
}
}

Text { colspan: 3; }
Expand Down

0 comments on commit c7f8bb9

Please sign in to comment.