Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ categories = [ "algorithms", "data-structures", "science" ]
license = "MIT OR Apache-2.0"
name = "num-bigint"
repository = "https://github.com/rust-num/num-bigint"
version = "0.4.2"
version = "0.4.3"
readme = "README.md"
build = "build.rs"
exclude = ["/bors.toml", "/ci/*", "/.github/*"]
Expand Down
9 changes: 9 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Release 0.4.3 (2021-11-02)

- [GHSA-v935-pqmr-g8v9]: [Fix unexpected panics in multiplication.][228]

**Contributors**: @arvidn, @cuviper, @guidovranken

[228]: https://github.com/rust-num/num-bigint/pull/228
[GHSA-v935-pqmr-g8v9]: https://github.com/rust-num/num-bigint/security/advisories/GHSA-v935-pqmr-g8v9

# Release 0.4.2 (2021-09-03)

- [Use explicit `Integer::div_ceil` to avoid the new unstable method.][219]
Expand Down
22 changes: 14 additions & 8 deletions src/biguint/multiplication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,20 @@ fn bigint_from_slice(slice: &[BigDigit]) -> BigInt {
fn mac3(mut acc: &mut [BigDigit], mut b: &[BigDigit], mut c: &[BigDigit]) {
// Least-significant zeros have no effect on the output.
if let Some(&0) = b.first() {
let nz = b.iter().position(|&d| d != 0).unwrap();
b = &b[nz..];
acc = &mut acc[nz..];
if let Some(nz) = b.iter().position(|&d| d != 0) {
b = &b[nz..];
acc = &mut acc[nz..];
} else {
return;
}
}
if let Some(&0) = c.first() {
let nz = c.iter().position(|&d| d != 0).unwrap();
c = &c[nz..];
acc = &mut acc[nz..];
if let Some(nz) = c.iter().position(|&d| d != 0) {
c = &c[nz..];
acc = &mut acc[nz..];
} else {
return;
}
}

let acc = acc;
Expand Down Expand Up @@ -168,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 @@ -344,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
Original file line number Diff line number Diff line change
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
185 changes: 185 additions & 0 deletions tests/fuzzed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
//! Check buggy inputs that were found by fuzzing

use num_bigint::BigUint;
use num_traits::Num;

#[test]
fn fuzzed_mul_1() {
let hex1 = "\
cd6839ee857cf791a40494c2e522846eefbca9eca9912fdc1feed4561dbde75c75f1ddca2325ebb1\
b9cd6eae07308578e58e57f4ddd7dc239b4fd347b883e37d87232a8e5d5a8690c8dba69c97fe8ac4\
58add18be7e460e03c9d1ae8223db53d20681a4027ffc17d1e43b764791c4db5ff7add849da7e378\
ac8d9be0e8b517c490da3c0f944b6a52a0c5dc5217c71da8eec35d2c3110d8b041d2b52f3e2a8904\
abcaaca517a8f2ef6cd26ceadd39a1cf9f770bc08f55f5a230cd81961348bb18534245430699de77\
d93b805153cffd05dfd0f2cfc2332888cec9c5abf3ece9b4d7886ad94c784bf74fce12853b2a9a75\
b62a845151a703446cc20300eafe7332330e992ae88817cd6ccef8877b66a7252300a4664d7074da\
181cd9fd502ea1cd71c0b02db3c009fe970a7d226382cdba5b5576c5c0341694681c7adc4ca2d059\
d9a6b300957a2235a4eb6689b71d34dcc4037b520eabd2c8b66604bb662fe2bcf533ba8d242dbc91\
f04c1795b9f0fee800d197d8c6e998248b15855a9602b76cb3f94b148d8f71f7d6225b79d63a8e20\
8ec8f0fa56a1c381b6c09bad9886056aec17fc92b9bb0f8625fd3444e40cccc2ede768ddb23c66ad\
59a680a26a26d519d02e4d46ce93cce9e9dd86702bdd376abae0959a0e8e418aa507a63fafb8f422\
83b03dc26f371c5e261a8f90f3ac9e2a6bcc7f0a39c3f73043b5aa5a950d4e945e9f68b2c2e593e3\
b995be174714c1967b71f579043f89bfce37437af9388828a3ba0465c88954110cae6d38b638e094\
13c15c9faddd6fb63623fd50e06d00c4d5954e787158b3e4eea7e9fae8b189fa8a204b23ac2f7bbc\
b601189c0df2075977c2424336024ba3594172bea87f0f92beb20276ce8510c8ef2a4cd5ede87e7e\
38b3fa49d66fbcd322be686a349c24919f4000000000000000000000000000000000000000000000\
000000000000000000000000000000000";
let hex2 = "\
40000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000007";

// Result produced independently in Python
let hex_result = "\
335a0e7ba15f3de469012530b948a11bbbef2a7b2a644bf707fbb515876f79d71d7c777288c97aec\
6e735bab81cc215e396395fd3775f708e6d3f4d1ee20f8df61c8caa39756a1a43236e9a725ffa2b1\
162b7462f9f918380f2746ba088f6d4f481a069009fff05f4790edd91e47136d7fdeb7612769f8de\
2b2366f83a2d45f124368f03e512da94a831771485f1c76a3bb0d74b0c44362c1074ad4bcf8aa241\
2af2ab2945ea3cbbdb349b3ab74e6873e7ddc2f023d57d688c33606584d22ec614d09150c1a6779d\
f64ee01454f3ff4177f43cb3f08cca2233b2716afcfb3a6d35e21ab6531e12fdd3f384a14ecaa69d\
6d8aa1145469c0d11b3080c03abf9ccc8cc3a64aba2205f35b33be21ded9a9c948c02919935c1d36\
8607367f540ba8735c702c0b6cf0027fa5c29f4898e0b36e96d55db1700d05a51a071eb71328b416\
7669acc0255e888d693ad9a26dc74d373100ded483aaf4b22d99812ed98bf8af3d4ceea3490b6f24\
7c1305e56e7c3fba003465f631ba660922c56156a580addb2cfe52c52363dc7df58896de758ea388\
23b23c3e95a870e06db026eb6621815abb05ff24ae6ec3e1897f4d1139033330bb79da376c8f19ab\
5669a0289a89b546740b9351b3a4f33a7a77619c0af74ddaaeb8256683a39062a941e98febee3d08\
a0ec0f709bcdc7178986a3e43ceb278a9af31fc28e70fdcc10ed6a96a54353a517a7da2cb0b964f8\
ee656f85d1c530659edc7d5e410fe26ff38dd0debe4e220a28ee811972225504432b9b4e2d8e3825\
04f05727eb775bed8d88ff54381b40313565539e1c562cf93ba9fa7eba2c627ea28812c8eb0bdeef\
2d804627037c81d65df09090cd8092e8d6505cafaa1fc3e4afac809db3a144323bca93358117f935\
13d3695771180f461cf38bb995b531c9e072f84f04df87ce5ad0315387399d1086f60971dc149e06\
c23253a64e46e467b210e704f93f2ec6f60b9b386eb1f629e48d79adf57e018e4827f5cb5e6cc0ba\
d3573ea621a84bbc58efaff4abe2d8b7c117fe4a6bd3da03bf4fc61ff9fc5c0ea04f97384cb7df43\
265cf3a65ff5f7a46d0e0fe8426569063ea671cf9e87578c355775ecd1ccc2f44ab329bf20b28ab8\
83a59ea48bf9c0fa6c0c936cad5c415243eb59b76f559e8b1a86fd1daa46cfe4d52e351546f0a082\
394aafeb291eb6a3ae4f661bbda78467b3ab7a63f1e4baebf1174a13c32ea281a49e2a3937fb299e\
393b9116def94e15066cf5265f6566302c5bb8a69df9a8cbb45fce9203f5047ecc1e1331f6a8c9f5\
ed31466c9e1c44d13fea4045f621496bf0b893a0187f563f68416c9e0ed8c75c061873b274f38ee5\
041656ef77826fcdc401cc72095c185f3e66b2c37cfcca211fcb4f332ab46a19dbfd4027fd9214a5\
181596f85805bb26ed706328ffcd96a57a1a1303f8ebd10d8fdeec1dc6daf08054db99e2e3e77e96\
d85e6c588bff4441bf2baa25ec74a7e803141d6cab09ec6de23c5999548153de0fdfa6cebd738d84\
70e70fd3b4b1441cefa60a9a65650ead11330c83eb1c24173665e3caca83358bbdce0eacf199d1b0\
510a81c6930ab9ecf6a9b85328f2977947945bc251d9f7a87a135d260e965bdce354470b3a131832\
a2f1914b1d601db64f1dbcc43ea382d85cd08bb91c7a161ec87bc14c7758c4fc8cfb8e240c8a4988\
5dc10e0dfb7afbed3622fb0561d715254b196ceb42869765dc5cdac5d9c6e20df9b54c6228fa07ac\
44619e3372464fcfd67a10117770ca23369b796d0336de113fa5a3757e8a2819d9815b75738cebd8\
04dd0e29c5f334dae77044fffb5ac000000000000000000000000000000000000000000000000000\
000000000000000000000000000";

let bn1 = &BigUint::from_str_radix(hex1, 16).unwrap();
let bn2 = &BigUint::from_str_radix(hex2, 16).unwrap();
let result = BigUint::from_str_radix(hex_result, 16).unwrap();

assert_eq!(bn1 * bn2, result);
assert_eq!(bn2 * bn1, result);
}

#[test]
fn fuzzed_mul_2() {
let hex_a = "\
812cff04ff812cff04ff8180ff80ffff11ff80ff2cff04ff812cff04ff812cff04ff81232cff047d\
ff04ff812cff04ff812cff04ff812cff047f812cff04ff8180ff2cff04ff04ff8180ff2cff04ff04\
ff812cbf04ff8180ff2cff04ff812cff0401010000000000000000ffff1a80ffc006c70084ffff80\
ffc0064006000084ffff72ffc020ffffffffffff06d709000000dbffffffc799999999b999999999\
99999999000084ffff72ffc02006e1ffffffc70900ffffff00f312ff80ebffffff6f505f6c2e6712\
108970ffff5f6c6f6727020000000000007400000000000000000000a50000000000000000000000\
000000000000000000000000ff812cff04ff812cff2c04ff812cff8180ff2cff04ff04ff818b8b8b\
8b8b8b8b8b8b8b8b8b8b8b8b8b06c70084ffff80ffc006c700847fff80ffc006c700ffff12c70084\
ffff80ffc0060000000000000056ff00c789bfff80ffc006c70084ffff80ffc006c700ffff840100\
00000000001289ffc08b8b8b8b8b8b8b2c";
let hex_b = "\
7ed300fb007ed300fb007e7f00db00fb007ed3007ed300fb007edcd300fb8200fb007ed300fb007e\
d300fb007ed300fb007ed300fbfeffffffffffffa8fb007e7f00d300fb00fb007ed340fb007e7f00\
00fb007ed300fb007ed300fb007e7f00d300fb00fb007e7f00d300fb007efb007e7f00d300fb007e\
d300fb007e7f0097d300fb00bf007ed300fb007ed300fb00fb00fb00fbffffffffffffffffffff00\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
000000000000df9b3900ff908fa08d9e968c9a0000e7fffb7fff0000003fd9004c90d8f600de7f00\
3fdf9b3900ff908fa08d9e968cf9b9ff0000ed38ff7b00007f003ff9ffffffffffffffa900ff3876\
000078003ff938ff7b00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d300\
fb00fb007e7f00d300fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb017e\
d300fb007ed300fb007edcd300fb8200fb007e0000e580";
let hex_c = "\
7b00387ffff938ff7b80007f003ff9b9ff00fdec38ff7b00007f003ff9ffffffffffffffa900ff38\
76000078003ff938ff7b00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d3\
00fb00fb007e7f00d300fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb01\
7ed300fb007ed300fb007edcd300fb8200fb007e000000ee7f003f0000007b00387ffff938ff7b80\
007f003ff9b9ff00fdec38ff7b00007f003ff9ffffffffffffffa900ff3876000078003ff938ff7b\
00007f003ff938ff00007bfeffffffffffffed76003f74747474747474d300fb00fb007e7f00d300\
fb007efb007e7f00d3003e7f007ed300fb007ed300fb007e7f00d300fb017ed300fb007ed300fb00\
7edcd300fb8200fb007e000000ee7f003f000000000000000000000000000000002a000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000000000000000\
0000000000000000000000df9b3900ff908fa08d9e968c9a0000e7fffb7fff0000003fd9004c90d8\
f600de7f003fdf9b3900ff908fa08d9e968c9a0000e7fffa7fff0000004005004c90d8f600de908f\
dcd300fb8200fb007e0000e57f003ff938ff7b00007f003d7ed300fb007ed300fb007ed300fb007e\
fa00fb007ed300fbf9ffffffffffffffa900ff387600007f003ff938ff7b00007f003ff938fd0000\
7bfeffffffffffffed76003f74747474747474d300fc";

// Result produced independently in Python
let hex_result = "\
1ebf6415da7ac71a689cd450727b7a361402a1626e0b6cd057e0e2a77d4cb722c1b7d0cbd73a7c07\
d756813fe97d73d5905c4a26404c7162769ba2dbc1e2742855a1db803e2d2c2fddc77c0598cc70fe\
066fd4b81cae3e23c55b4795de63acacd1343cf5ad5e715e6919d140c01bab1af1a737ebbf8a7775\
7602acd611f555ee2d5be56cc14b97c248009cd77490a3dfd6762bae25459a544e369eb4b0cc952a\
8e6a551ff35a4a7a6e5f5b0b72495c4baadf3a26b9d5d97402ad60fa2324e93adc96ca159b62d147\
5695f26ff27da100a76e2d273420572e61b4dfbd97e826d9d946f85b87434523f6aa7ce43c443285\
33f5b5adf32574167b1e9ea3bf6254d6afacf865894907de196285169cfcc1c0fcf438873d13f7e8\
654acc27c1abb00bec2729e34c994ff2152f60406f75db3ab616541795d9db8ca0b381148de7875f\
e7a8191407abc390718003698ca28498948caf1dbc3f02593dd85fa929ebae86cfe783d7be473e98\
0060d9ec60843661cb4cb9b8ddb24bb710f93700b22530501b5ea26c5c94c7370fe0ccbafe0ce7e4\
cd4f071d0cf0ac151c85a5b132ecaa75793abfb4a6ee33fddd2aa2f5cf2a8eb19c75322792c0d8dc\
1efb2dcd8ae2b49dd57b84898f531c7f745464f637716151831db56b3e293f587dc95a5e12edfe6b\
8458033dddf3556da55bef55ba3c3769def0c0f0c86786aca8313dc0ce09118760721eb545d69b46\
cdb89d377f2c80e67b572da0f75760c2849288a8457c18c6f0b58244b7f95a7567ce23756f1fe359\
64f7e84fbe28b188157519dd99b8798b076e21984d15c37f41da1309e0fbc539e8b9b09fed36a908\
28c94f72e7b755c187e58db6bfef0c02309086626ad0fe2efd2ff1467b3de11e057687865f4f85e7\
0a39bcbc4674dcaded9b04562afe08eb92fbd96ea4a99aa4f9347a075d4421f070ce3a33225f5af1\
9c27ec5d1720e659ca7fff9686f46b01d76d7de64c738671aaec57ee5582ef7956206fb37c6a36f8\
8f226ce2124a7f9894a0e9a7aa02001746e6def35699d7adc84a7dcf513ff3da20fd849950f41a5d\
bb02c91666697156d69ebbe2ef26732b6595d1b6d014a60006d2d3c7055ff9b531779195b8dcd7d9\
426e776cbc9041735384568ba4adbf7eeea7e0e6cbb47b70335a7ed12a68904eecd334921e4ae6d9\
c983af20d73215c39573963f03bc87082450cc1c70250e1e8eaa318acaf044a072891fc60324d134\
6c0a1d02cceb4d4806e536d6017bf6bc125c41694ded38766fea51bfbf7a008ca0b3eb1168766486\
8aa8469b3e6787a5d5bad6cd67c24005a5cbaa10b63d1b4d05ac42a8b31263052a1260b5900be628\
4dcab4eb0cf5cda815412ced7bd78f87c00ac3581f41a04352a4a186805a5c9e37b14561a5fc97d2\
52ca4654fe3d82f42080c21483789cc4b4cbb568f79844f7a317aa2a6555774da26c6f027d3cb0ee\
9276c6dc4f285fc3b4b9a3cd51c8815cebf110e73c80a9b842cc3b7c80af13f702662b10e868eb61\
947000b390cd2f3a0899f6f1bab86acf767062f5526507790645ae13b9701ba96b3f873047c9d3b8\
5e8a5d904a01fbfe10e63495b6021e7cc082aa66679e4d92b3e4e2d62490b44f7e250584cedff0e7\
072a870ddaa9687a1eae11afc874d83065fb98dbc3cfd90f39517ff3015c71a8c0ab36a6483c7b87\
f41b2c832fa9428fe95ffba4e49cc553d9e2d33a540958da51588e5120fef6497bfaa96a4dcfc024\
8170c57f78e9ab9546efbbaf8e9ad6a993493577edd3d29ce8fd9a2e9eb4363b5b472a4ecb2065eb\
38f876a841af1f227a703248955c8978329dffcd8e065d8da4d42504796ff7abc62832ed86c4f8d0\
0f55cd567fb9d42524be57ebdacef730c3f94c0372f86fa1b0114f8620f553e4329b2a586fcfeedc\
af47934909090e14a1f1204e6f1681fb2df05356381e6340f4feaf0787e06218b0b0d8df51acb0bc\
f98546f33273adf260da959d6fc4a04872122af6508d124abb963c14c30e7c07fee368324921fe33\
9ae89490c5d6cdae0c356bb6921de95ea13b54e23800";

let a = &BigUint::from_str_radix(hex_a, 16).unwrap();
let b = &BigUint::from_str_radix(hex_b, 16).unwrap();
let c = &BigUint::from_str_radix(hex_c, 16).unwrap();
let result = BigUint::from_str_radix(hex_result, 16).unwrap();

assert_eq!(a * b * c, result);
assert_eq!(a * c * b, result);
assert_eq!(b * a * c, result);
assert_eq!(b * c * a, result);
assert_eq!(c * a * b, result);
assert_eq!(c * b * a, result);
}