From 35f240e453c480d1c5be68a0977fcf56d4ac5550 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 24 Oct 2026 13:53:26 +0000 Subject: [PATCH] Return BadParams for overflowing start in review.spellingChange Found while testing crates/engine/src/cmd/review.rs:424 (spelling_change) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/review.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/review.rs b/crates/engine/src/cmd/review.rs index 1d2969e0..99e8aba3 100644 --- a/crates/engine/src/cmd/review.rs +++ b/crates/engine/src/cmd/review.rs @@ -430,7 +430,7 @@ fn spelling_change(s: &mut Session, p: &Value) -> Result { // One exact occurrence (a squiggled word): paragraph `para`, from character `start`. if let (Some(id), Some(para), Some(start)) = (shape, usize_param(p, "para"), usize_param(p, "start")) { let id = deckcraft_model::ShapeId(u32::try_from(id).map_err(|_| bad("review.spellingChange", "bad `shape`"))?); - let end = start + word.chars().count(); + let end = start.checked_add(word.chars().count()).ok_or_else(|| bad("review.spellingChange", "bad `start`"))?; let cell = usize_param(p, "row").zip(usize_param(p, "col")); let slide = { let st = s.doc()?; @@ -843,3 +843,18 @@ mod tests { assert!(s.active().unwrap().doc.slides[0].comments.is_empty()); } } + +#[cfg(test)] +mod spelling_change_range_tests { + use crate::{EngineError, Session}; + use serde_json::json; + + #[test] + fn spelling_change_huge_start_is_bad_params() { + let mut s = Session::with_new(); + let r = s.execute("insert.textBox", &json!({"text": "Hello"})).unwrap(); + let id = r["id"].clone(); + let err = s.execute("review.spellingChange", &json!({"shape": id, "para": 0, "start": u64::MAX, "word": "Hello", "to": "x"})).unwrap_err(); + assert!(matches!(err, EngineError::BadParams { .. }), "{err:?}"); + } +}