From 620be76873d21f934620aea24cdde6ba49f464c2 Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Mon, 19 Oct 2026 10:48:47 +0000 Subject: [PATCH] Reject signed and multi-$ whole-row ranges in RangeRef::parse Found while testing crates/core/src/addr.rs:217 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/core/src/addr.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/core/src/addr.rs b/crates/core/src/addr.rs index 2bdfe797a..4780158e8 100644 --- a/crates/core/src/addr.rs +++ b/crates/core/src/addr.rs @@ -214,7 +214,14 @@ impl RangeRef { if let (Some(x), Some(y)) = (letters_to_col(&strip(a)), letters_to_col(&strip(b))) { return Some(RangeRef::cols(x.min(y), x.max(y))); } - let (pa, pb) = (strip(a).parse::().ok()?, strip(b).parse::().ok()?); + let row_num = |t: &str| { + let t = t.strip_prefix('$').unwrap_or(t); + if t.is_empty() || !t.bytes().all(|c| c.is_ascii_digit()) { + return None; + } + t.parse::().ok() + }; + let (pa, pb) = (row_num(a)?, row_num(b)?); if pa == 0 || pb == 0 || pa > MAX_ROWS || pb > MAX_ROWS { return None; } @@ -234,6 +241,16 @@ impl fmt::Display for RangeRef { mod tests { use super::*; + #[test] + fn range_parse_rejects_signed_rows() { + assert!(RangeRef::parse("+1:+3").is_none()); + assert!(RangeRef::parse("-1:3").is_none()); + assert!(RangeRef::parse("$$1:3").is_none()); + assert!(RangeRef::parse(":3").is_none()); + let r = RangeRef::parse("$1:$3").unwrap(); + assert_eq!((r.start.row, r.end.row), (0, 2)); + } + #[test] fn letters_roundtrip() { for (c, s) in [(0, "A"), (25, "Z"), (26, "AA"), (51, "AZ"), (52, "BA"), (701, "ZZ"), (702, "AAA"), (16383, "XFD")] {