From 9e14fd072242f920baa3f786d306d8e92517d723 Mon Sep 17 00:00:00 2001 From: Racum Date: Sun, 8 Dec 2024 11:32:41 -0300 Subject: [PATCH 1/3] Add check for u64 overflows --- src/lib.rs | 15 +++++++++++---- tests/decoding.rs | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 tests/decoding.rs diff --git a/src/lib.rs b/src/lib.rs index e2a7d0d..4d4d539 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -251,7 +251,10 @@ impl Sqids { let alphabet_without_separator: Vec = alphabet.iter().copied().skip(1).collect(); - ret.push(self.to_number(chunks[0], &alphabet_without_separator)); + match self.to_number(chunks[0], &alphabet_without_separator) { + Some(value) => ret.push(value), + None => (), + } if chunks.len() > 1 { alphabet = Self::shuffle(&alphabet); @@ -332,15 +335,19 @@ impl Sqids { id.into_iter().collect() } - fn to_number(&self, id: &str, alphabet: &[char]) -> u64 { + fn to_number(&self, id: &str, alphabet: &[char]) -> Option { let mut result = 0; for c in id.chars() { let idx = alphabet.iter().position(|&x| x == c).unwrap(); - result = result * alphabet.len() as u64 + idx as u64; + result = result * alphabet.len() as u128 + idx as u128; } - result + if result <= u64::MAX.into() { + Some(result.try_into().unwrap()) + } else { + None + } } fn shuffle(alphabet: &[char]) -> Vec { diff --git a/tests/decoding.rs b/tests/decoding.rs new file mode 100644 index 0000000..f012a53 --- /dev/null +++ b/tests/decoding.rs @@ -0,0 +1,15 @@ +use sqids::*; + +#[test] +fn decode_number_maximum_value() { + let sqids = Sqids::default(); + let numbers = sqids.decode("ABARpJzdz9"); + assert_eq!(numbers, [9_007_199_254_740_991]); // 2 ^ 53 +} + +#[test] +fn decode_number_overflows() { + let sqids = Sqids::default(); + let numbers = sqids.decode("0J4AEXRN106Z0"); + assert_eq!(numbers, Vec::::new()); +} From 7a0e082f14571f8633a6c47e744983ef54a4360d Mon Sep 17 00:00:00 2001 From: Racum Date: Sun, 8 Dec 2024 11:35:10 -0300 Subject: [PATCH 2/3] Apply suggestions from cargo fmt and clippy --- src/lib.rs | 5 ++--- tests/decoding.rs | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4d4d539..f16f0bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -251,9 +251,8 @@ impl Sqids { let alphabet_without_separator: Vec = alphabet.iter().copied().skip(1).collect(); - match self.to_number(chunks[0], &alphabet_without_separator) { - Some(value) => ret.push(value), - None => (), + if let Some(value) = self.to_number(chunks[0], &alphabet_without_separator) { + ret.push(value) } if chunks.len() > 1 { diff --git a/tests/decoding.rs b/tests/decoding.rs index f012a53..ce3d1b7 100644 --- a/tests/decoding.rs +++ b/tests/decoding.rs @@ -3,13 +3,13 @@ use sqids::*; #[test] fn decode_number_maximum_value() { let sqids = Sqids::default(); - let numbers = sqids.decode("ABARpJzdz9"); - assert_eq!(numbers, [9_007_199_254_740_991]); // 2 ^ 53 + let numbers = sqids.decode("ABARpJzdz9"); + assert_eq!(numbers, [9_007_199_254_740_991]); // 2 ^ 53 } #[test] fn decode_number_overflows() { let sqids = Sqids::default(); - let numbers = sqids.decode("0J4AEXRN106Z0"); + let numbers = sqids.decode("0J4AEXRN106Z0"); assert_eq!(numbers, Vec::::new()); } From c1d42403a2cca14b503e9545f660a181e51eab92 Mon Sep 17 00:00:00 2001 From: Racum Date: Sun, 8 Dec 2024 11:37:16 -0300 Subject: [PATCH 3/3] Bump version and update changelog --- CHANGELOG.md | 3 +++ Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 532800e..3e7e49e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # CHANGELOG +**v0.4.2:** +- Fix u64 overflow + **v0.4.1:** - Derive `Clone` trait [[PR #6](https://github.com/sqids/sqids-rust/pull/6)] - Cargo update diff --git a/Cargo.toml b/Cargo.toml index b46fa52..b469efd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ description = "Generate short unique ids from numbers." repository = "https://github.com/sqids/sqids-rust" documentation = "https://docs.rs/sqids" homepage = "https://sqids.org/rust" -version = "0.4.1" +version = "0.4.2" license = "MIT" edition = "2021" readme = "README.md"