From 26f8a879ee2c65d7214acdaa4ec0ee39cdde18e1 Mon Sep 17 00:00:00 2001 From: James Date: Sat, 29 Jul 2023 16:29:24 -0700 Subject: [PATCH 1/2] feat: check from base len to prevent consuming large iters --- src/base_convert.rs | 51 +++++++++++++++++++++++++++++++++++++++++---- src/string.rs | 5 +++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/base_convert.rs b/src/base_convert.rs index 3c21d162..d7562d2f 100644 --- a/src/base_convert.rs +++ b/src/base_convert.rs @@ -125,9 +125,24 @@ impl Uint { return Err(BaseConvertError::InvalidBase(base)); } - let mut tail = digits.into_iter(); - match tail.next() { - Some(digit) => Self::from_base_le_recurse(digit, base, &mut tail), + // we compute this by dividing the number of bits in the Uint by the + // number of bits in each word, rounding up. + let max_digits: usize = BITS / (usize::BITS - base.leading_zeros()) as usize + 1; + + let mut iter = digits.into_iter(); + let mut digits = iter.by_ref().take(max_digits); + + match digits.next() { + Some(digit) => { + let res = Self::from_base_le_recurse::(digit, base, digits)?; + + // if the iter was not drained during the recursion process, + // then we have overflowed + if iter.next().is_some() { + return Err(BaseConvertError::Overflow); + } + Ok(res) + } None => Ok(Self::ZERO), } } @@ -141,7 +156,7 @@ impl Uint { fn from_base_le_recurse>( digit: u64, base: u64, - tail: &mut I, + mut tail: core::iter::Take<&mut I>, ) -> Result { if digit > base { return Err(BaseConvertError::InvalidDigit(digit, base)); @@ -176,11 +191,22 @@ impl Uint { return Err(BaseConvertError::InvalidBase(base)); } + // we compute this by dividing the number of bits in the Uint by the + // number of bits in each word, rounding up. + let max_digits: usize = BITS / (usize::BITS - base.leading_zeros()) as usize + 1; + + let mut iter = digits.into_iter(); + let digits = iter.by_ref().take(max_digits); + let mut result = Self::ZERO; for digit in digits { result.add_digit(digit, base)?; } + if iter.next().is_some() { + return Err(BaseConvertError::Overflow); + } + Ok(result) } } @@ -265,6 +291,19 @@ mod tests { .unwrap(), N ); + + assert_eq!( + Uint::<4, 1>::from_base_le(10, [6, 1]), + Err(BaseConvertError::Overflow), + ); + assert_eq!( + Uint::<4, 1>::from_base_le(10, [5, 1, 318]), + Err(BaseConvertError::Overflow), + ); + assert_eq!( + Uint::<4, 1>::from_base_le(10, [5, 1]), + Ok(Uint::<4, 1>::from(15)), + ); } #[test] @@ -308,6 +347,10 @@ mod tests { #[test] fn test_from_base_be_overflow() { + assert_eq!( + Uint::<1, 1>::from_base_be(10, std::iter::repeat(0)), + Err(BaseConvertError::Overflow) + ); assert_eq!( Uint::<0, 0>::from_base_be(10, [].into_iter()), Ok(Uint::<0, 0>::ZERO) diff --git a/src/string.rs b/src/string.rs index 73f858ef..425b6b56 100644 --- a/src/string.rs +++ b/src/string.rs @@ -255,4 +255,9 @@ mod tests { assert_eq!(format!("{n:#b}"), format!("{value:#066b}")); }); } + + #[test] + fn test_from_hex_extra_zeroes() { + Uint::<16, 1>::from_str("0x00000000000001").unwrap(); + } } From 6a2e2dc9b7eea8379930f7414639b27ef81b2fea Mon Sep 17 00:00:00 2001 From: James Date: Sat, 29 Jul 2023 16:52:48 -0700 Subject: [PATCH 2/2] doc: better commenting --- src/base_convert.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/base_convert.rs b/src/base_convert.rs index d7562d2f..8680acd4 100644 --- a/src/base_convert.rs +++ b/src/base_convert.rs @@ -203,6 +203,7 @@ impl Uint { result.add_digit(digit, base)?; } + // If the iterator still contains digits, we have overflowed. if iter.next().is_some() { return Err(BaseConvertError::Overflow); }