From 8008707fea97b9215f3b949a0eb6044aec709a31 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 26 Oct 2021 19:10:45 -0700 Subject: [PATCH] Fix an undersized buffer panic in multiplication Reported-by: Guido Vranken Reported-by: Arvid Norberg --- src/biguint/multiplication.rs | 4 ++-- tests/biguint.rs | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/biguint/multiplication.rs b/src/biguint/multiplication.rs index ce966bc7..597a2029 100644 --- a/src/biguint/multiplication.rs +++ b/src/biguint/multiplication.rs @@ -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 @@ -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); diff --git a/tests/biguint.rs b/tests/biguint.rs index 5a5979c4..821b754a 100644 --- a/tests/biguint.rs +++ b/tests/biguint.rs @@ -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() {