Repository: sharkdp/bat (language: rust)

Issue:
Arithmetic overflow occurs while using API LineRange::from()
<!--

Hey there, thank you for reporting a bug!

Please note that the following bugs have already been reported:

* dpkg: error processing archive /some/path/some-program.deb (--unpack):
  trying to overwrite '/usr/.crates2.json'

  See https://github.com/sharkdp/bat/issues/938

-->

**What steps will reproduce the bug?**
I executed fuzz testing with `bat` public APIs and found crash case.

~~~
let fuzz_arg1 = "18446744073709551615:+1";
LineRange::from(fuzz_arg1);
~~~


**What happens?**

~~~
Thread '<unnamed>' panicked at 'attempt to add with overflow', /rustc/871b5952023139738f72eba235063575062bc2e9/library/core/src/ops/arith.rs:109
~~~

The overflow occurs with this statement : 

https://github.com/sharkdp/bat/blob/5a240f36b9251fd6513316333acb969a4d347b9d/src/line_range.rs#L56

**What did you expect to happen instead?**
Need assertion to prevent arith overflow, or need to explicitly mention panic condition. 


Discussion / hints:
Maybe `saturating_add(new_range.lower, more_lines)` can be done here to avoid panicking.
> Maybe `saturating_add(new_range.lower, more_lines)` can be done here to avoid panicking.

Looks nice, better than `assert!`.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de9175e154..81b86bc572 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@
 - Fix `more` not being found on Windows when provided via `BAT_PAGER`, see #2570, #2580, and #2651 (@mataha)
 - Switched default behavior of `--map-syntax` to be case insensitive #2520
 - Updated version of `serde_yaml` to `0.9`. See #2627 (@Raghav-Bell)
+- Fixed arithmetic overflow in `LineRange::from`, see #2674 (@skoriop)
+
 ## Other
 
 - Output directory for generated assets (completion, manual) can be customized, see #2515 (@tranzystorek-io)
diff --git a/src/line_range.rs b/src/line_range.rs
index c9094fc9e0..8899c70601 100644
--- a/src/line_range.rs
+++ b/src/line_range.rs
@@ -53,7 +53,7 @@ impl LineRange {
                     let more_lines = &line_numbers[1][1..]
                         .parse()
                         .map_err(|_| "Invalid character after +")?;
-                    new_range.lower + more_lines
+                    new_range.lower.saturating_add(*more_lines)
                 } else if first_byte == Some(b'-') {
                     // this will prevent values like "-+5" even though "+5" is valid integer
                     if line_numbers[1][1..].bytes().next() == Some(b'+') {
@@ -128,6 +128,13 @@ fn test_parse_plus() {
     assert_eq!(50, range.upper);
 }
 
+#[test]
+fn test_parse_plus_overflow() {
+    let range = LineRange::from(&format!("{}:+1", usize::MAX)).expect("Shouldn't fail on test!");
+    assert_eq!(usize::MAX, range.lower);
+    assert_eq!(usize::MAX, range.upper);
+}
+
 #[test]
 fn test_parse_plus_fail() {
     let range = LineRange::from("40:+z");


Test patch: