diff --git a/crates/calc/src/eval.rs b/crates/calc/src/eval.rs index 92a0a39..65de8b0 100644 --- a/crates/calc/src/eval.rs +++ b/crates/calc/src/eval.rs @@ -1152,7 +1152,8 @@ impl<'h> Evaluator<'h> { } match src { Ev::R(areas) => { - let Some(a) = areas.get((area_n - 1).max(0) as usize).copied() else { return err(CellError::Ref) }; + let area = usize::try_from((area_n as u64).saturating_sub(1)).ok(); + let Some(a) = area.and_then(|i| areas.get(i)).copied() else { return err(CellError::Ref) }; let r = a.range; // A single row or column with one index picks along it. let (row, col) = if two_args && r.height() == 1 { (1, row) } else { (row, col) }; diff --git a/crates/calc/src/tests.rs b/crates/calc/src/tests.rs index 5133409..aa9d460 100644 --- a/crates/calc/src/tests.rs +++ b/crates/calc/src/tests.rs @@ -157,6 +157,21 @@ fn index_with_arrays_of_positions() { assert_eq!(t.num("E7"), 6.0); } +#[test] +fn index_area_number_overflow() { + let mut t = T::new(); + t.set("A1", "7"); + t.set("D1", "9"); + for (area, expected) in [("1", 7.0), ("2", 9.0)] { + t.set("G5", &format!("=INDEX((A1:B2,D1:E2),1,1,{area})")); + assert_eq!(t.num("G5"), expected, "area {area}"); + } + for area in ["3", "1E300", "-1", "-1E300"] { + t.set("G5", &format!("=INDEX((A1:B2,D1:E2),1,1,{area})")); + assert_eq!(t.get("G5"), Value::Error(CellError::Ref), "area {area}"); + } +} + #[test] fn errors_and_cycles() { let mut t = T::new();