Skip to content

Commit

Permalink
Merge pull request #7 from Racum/number-overflow
Browse files Browse the repository at this point in the history
Fix u64 overflow when decoding
  • Loading branch information
4kimov authored Dec 21, 2024
2 parents 8e40263 + c1d4240 commit c517814
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ impl Sqids {

let alphabet_without_separator: Vec<char> =
alphabet.iter().copied().skip(1).collect();
ret.push(self.to_number(chunks[0], &alphabet_without_separator));
if let Some(value) = self.to_number(chunks[0], &alphabet_without_separator) {
ret.push(value)
}

if chunks.len() > 1 {
alphabet = Self::shuffle(&alphabet);
Expand Down Expand Up @@ -332,15 +334,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<u64> {
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<char> {
Expand Down
15 changes: 15 additions & 0 deletions tests/decoding.rs
Original file line number Diff line number Diff line change
@@ -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::<u64>::new());
}

0 comments on commit c517814

Please sign in to comment.