|
3 | 3 |
|
4 | 4 | use alloc::{vec, vec::Vec}; |
5 | 5 |
|
6 | | -use crypto_bigint::{Random, Uint}; |
| 6 | +use crypto_bigint::{CheckedAdd, Random, Uint}; |
7 | 7 | use rand_core::CryptoRngCore; |
8 | 8 |
|
9 | 9 | use crate::hazmat::precomputed::{SmallPrime, RECIPROCALS, SMALL_PRIMES}; |
@@ -75,10 +75,14 @@ impl<const L: usize> Sieve<L> { |
75 | 75 | /// Note that `start` is adjusted to `2`, or the next `1 mod 2` number (`safe_primes = false`); |
76 | 76 | /// and `5`, or `3 mod 4` number (`safe_primes = true`). |
77 | 77 | /// |
78 | | - /// Panics if `max_bit_length` is greater than the size of the target `Uint`. |
| 78 | + /// Panics if `max_bit_length` is zero or greater than the size of the target `Uint`. |
79 | 79 | /// |
80 | 80 | /// If `safe_primes` is `true`, both the returned `n` and `n/2` are sieved. |
81 | 81 | pub fn new(start: &Uint<L>, max_bit_length: usize, safe_primes: bool) -> Self { |
| 82 | + if max_bit_length == 0 { |
| 83 | + panic!("The requested bit length cannot be zero"); |
| 84 | + } |
| 85 | + |
82 | 86 | if max_bit_length > Uint::<L>::BITS { |
83 | 87 | panic!( |
84 | 88 | "The requested bit length ({}) is larger than the chosen Uint size", |
@@ -148,7 +152,13 @@ impl<const L: usize> Sieve<L> { |
148 | 152 | } |
149 | 153 |
|
150 | 154 | // Set the new base. |
151 | | - self.base = self.base.wrapping_add(&self.incr.into()); |
| 155 | + // Should not overflow since `incr` is never greater than `incr_limit`, |
| 156 | + // and the latter is chosen such that it doesn't overflow when added to `base` |
| 157 | + // (see the rest of this method). |
| 158 | + self.base = self |
| 159 | + .base |
| 160 | + .checked_add(&self.incr.into()) |
| 161 | + .expect("Integer overflow"); |
152 | 162 |
|
153 | 163 | self.incr = 0; |
154 | 164 |
|
@@ -206,7 +216,13 @@ impl<const L: usize> Sieve<L> { |
206 | 216 | let result = if self.current_is_composite() { |
207 | 217 | None |
208 | 218 | } else { |
209 | | - let mut num = self.base.wrapping_add(&self.incr.into()); |
| 219 | + // The overflow should never happen here since `incr` |
| 220 | + // is never greater than `incr_limit`, and the latter is chosen such that |
| 221 | + // it does not overflow when added to `base` (see `update_residues()`). |
| 222 | + let mut num = self |
| 223 | + .base |
| 224 | + .checked_add(&self.incr.into()) |
| 225 | + .expect("Integer overflow"); |
210 | 226 | if self.safe_primes { |
211 | 227 | num = (num << 1) | Uint::<L>::ONE; |
212 | 228 | } |
@@ -333,6 +349,12 @@ mod tests { |
333 | 349 | check_sieve(13, 4, true, &[]); |
334 | 350 | } |
335 | 351 |
|
| 352 | + #[test] |
| 353 | + #[should_panic(expected = "The requested bit length cannot be zero")] |
| 354 | + fn sieve_zero_bits() { |
| 355 | + let _sieve = Sieve::new(&U64::ONE, 0, false); |
| 356 | + } |
| 357 | + |
336 | 358 | #[test] |
337 | 359 | #[should_panic(expected = "The requested bit length (65) is larger than the chosen Uint size")] |
338 | 360 | fn sieve_too_many_bits() { |
|
0 commit comments