Skip to content

Commit

Permalink
Fix an undersized buffer panic in multiplication
Browse files Browse the repository at this point in the history
Reported-by: Guido Vranken <guidovranken@gmail.com>
Reported-by: Arvid Norberg <arvid.norberg@gmail.com>
  • Loading branch information
cuviper committed Oct 27, 2021
1 parent 0940e50 commit 8008707
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/biguint/multiplication.rs
Expand Up @@ -174,7 +174,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {

// We reuse the same BigUint for all the intermediate multiplies and have to size p
// appropriately here: x1.len() >= x0.len and y1.len() >= y0.len():
let len = x1.len() + y1.len();
let len = x1.len() + y1.len() + 1;
let mut p = BigUint { data: vec![0; len] };

// p2 = x1 * y1
Expand Down Expand Up @@ -350,7 +350,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {
}

fn mul3(x: &[BigDigit], y: &[BigDigit]) -> BigUint {
let len = x.len() + y.len();
let len = x.len() + y.len() + 1;
let mut prod = BigUint { data: vec![0; len] };

mac3(&mut prod.data, x, y);
Expand Down
16 changes: 15 additions & 1 deletion tests/biguint.rs
Expand Up @@ -1008,12 +1008,26 @@ fn test_checked_mul() {
#[test]
fn test_mul_overflow() {
// Test for issue #187 - overflow due to mac3 incorrectly sizing temporary
let s = "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502232636710047537552105951370000796528760829212940754539968588340162273730474622005920097370111";
let s = "5311379928167670986895882065524686273295931177270319231994441382\
0040355986085224273916250223263671004753755210595137000079652876\
0829212940754539968588340162273730474622005920097370111";
let a: BigUint = s.parse().unwrap();
let b = a.clone();
let _ = a.checked_mul(&b);
}

#[test]
fn test_mul_overflow_2() {
// Try a bunch of sizes that are right on the edge of multiplication length
// overflow, where (x * x).data.len() == 2 * x.data.len() + 1.
for i in 1u8..20 {
let bits = 1u32 << i;
let x = (BigUint::one() << bits) - 1u32;
let x2 = (BigUint::one() << (2 * bits)) - &x - &x - 1u32;
assert_eq!(&x * &x, x2);
}
}

#[test]
fn test_checked_div() {
for elm in MUL_TRIPLES.iter() {
Expand Down

0 comments on commit 8008707

Please sign in to comment.