Skip to content

Commit 8008707

Browse files
committed
Fix an undersized buffer panic in multiplication
Reported-by: Guido Vranken <guidovranken@gmail.com> Reported-by: Arvid Norberg <arvid.norberg@gmail.com>
1 parent 0940e50 commit 8008707

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/biguint/multiplication.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {
174174

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

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

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

356356
mac3(&mut prod.data, x, y);

tests/biguint.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -1008,12 +1008,26 @@ fn test_checked_mul() {
10081008
#[test]
10091009
fn test_mul_overflow() {
10101010
// Test for issue #187 - overflow due to mac3 incorrectly sizing temporary
1011-
let s = "531137992816767098689588206552468627329593117727031923199444138200403559860852242739162502232636710047537552105951370000796528760829212940754539968588340162273730474622005920097370111";
1011+
let s = "5311379928167670986895882065524686273295931177270319231994441382\
1012+
0040355986085224273916250223263671004753755210595137000079652876\
1013+
0829212940754539968588340162273730474622005920097370111";
10121014
let a: BigUint = s.parse().unwrap();
10131015
let b = a.clone();
10141016
let _ = a.checked_mul(&b);
10151017
}
10161018

1019+
#[test]
1020+
fn test_mul_overflow_2() {
1021+
// Try a bunch of sizes that are right on the edge of multiplication length
1022+
// overflow, where (x * x).data.len() == 2 * x.data.len() + 1.
1023+
for i in 1u8..20 {
1024+
let bits = 1u32 << i;
1025+
let x = (BigUint::one() << bits) - 1u32;
1026+
let x2 = (BigUint::one() << (2 * bits)) - &x - &x - 1u32;
1027+
assert_eq!(&x * &x, x2);
1028+
}
1029+
}
1030+
10171031
#[test]
10181032
fn test_checked_div() {
10191033
for elm in MUL_TRIPLES.iter() {

0 commit comments

Comments
 (0)