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 1/2] 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")] { From 8968e833592c4feedd7ac2fda6e777c3926758ed Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 19 Oct 2026 12:21:01 -0400 Subject: [PATCH 2/2] RangeRef::parse: whole columns take at most one $ too Co-Authored-By: Claude Opus 5.5 --- crates/core/src/addr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/core/src/addr.rs b/crates/core/src/addr.rs index 4780158e8..2c087f22e 100644 --- a/crates/core/src/addr.rs +++ b/crates/core/src/addr.rs @@ -210,7 +210,7 @@ impl RangeRef { if let (Some(x), Some(y)) = (CellRef::parse(a), CellRef::parse(b)) { return Some(RangeRef::new(x, y)); } - let strip = |t: &str| t.trim_start_matches('$').to_string(); + let strip = |t: &str| t.strip_prefix('$').unwrap_or(t).to_string(); 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))); } @@ -247,6 +247,8 @@ mod tests { assert!(RangeRef::parse("-1:3").is_none()); assert!(RangeRef::parse("$$1:3").is_none()); assert!(RangeRef::parse(":3").is_none()); + assert!(RangeRef::parse("$$A:$$C").is_none()); + assert!(RangeRef::parse("$A:$C").is_some()); let r = RangeRef::parse("$1:$3").unwrap(); assert_eq!((r.start.row, r.end.row), (0, 2)); }