aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-05 04:05:47 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-03-05 04:05:47 +0000
commit9e20480212911c937420f64be49775b121da2349 (patch)
treeec44dd90ddedf930b1d1122b8d8c5694d7d56374
parent1a70ff9a25ce097881be7e17eca883672057596c (diff)
parent0b1ccdfc5ad79493d6fef87cb36962aeb3fbc011 (diff)
downloadnum-bigint-android13-s2-release.tar.gz
Change-Id: I1e1a5b7694cb586d388ee49ee3e4072b290cac5c
-rw-r--r--.cargo_vcs_info.json2
-rw-r--r--Android.bp19
-rw-r--r--Cargo.toml11
-rw-r--r--METADATA10
-rw-r--r--RELEASES.md15
-rw-r--r--TEST_MAPPING6
-rw-r--r--out/probe0.ll4
-rw-r--r--out/probe1.ll4
-rw-r--r--out/probe2.ll4
-rw-r--r--out/probe3.ll4
-rw-r--r--src/biguint/multiplication.rs22
-rw-r--r--tests/biguint.rs16
-rw-r--r--tests/fuzzed.rs185
13 files changed, 270 insertions, 32 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 2c927ab..326b504 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,5 @@
{
"git": {
- "sha1": "8ee0b9ac69a43a44cbc648e3524e594e7db54eb3"
+ "sha1": "e77ffacafef7e8fa2c2b990489b7aa30dceaed64"
}
}
diff --git a/Android.bp b/Android.bp
index d49dd1e..1a9fd3f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -56,7 +56,7 @@ rust_library {
host_supported: true,
crate_name: "num_bigint",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.2",
+ cargo_pkg_version: "0.4.3",
srcs: [
"src/lib.rs",
":copy_num-bigint_build_out",
@@ -81,7 +81,7 @@ rust_test {
host_supported: true,
crate_name: "num_bigint",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.2",
+ cargo_pkg_version: "0.4.3",
srcs: [
"src/lib.rs",
":copy_num-bigint_build_out",
@@ -110,7 +110,7 @@ rust_defaults {
name: "num-bigint_test_defaults",
crate_name: "num_bigint",
cargo_env_compat: true,
- cargo_pkg_version: "0.4.2",
+ cargo_pkg_version: "0.4.3",
test_suites: ["general-tests"],
auto_gen_config: true,
edition: "2018",
@@ -195,6 +195,19 @@ rust_test {
}
rust_test {
+ name: "num-bigint_test_tests_fuzzed",
+ defaults: ["num-bigint_test_defaults"],
+ host_supported: true,
+ srcs: [
+ "tests/fuzzed.rs",
+ ":copy_num-bigint_build_out",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+rust_test {
name: "num-bigint_test_tests_modpow",
defaults: ["num-bigint_test_defaults"],
host_supported: true,
diff --git a/Cargo.toml b/Cargo.toml
index 54ccc1d..1c15d09 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,17 +3,16 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "num-bigint"
-version = "0.4.2"
+version = "0.4.3"
authors = ["The Rust Project Developers"]
build = "build.rs"
exclude = ["/bors.toml", "/ci/*", "/.github/*"]
diff --git a/METADATA b/METADATA
index 8ce088c..e0e6f54 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/num-bigint/num-bigint-0.4.2.crate"
+ value: "https://static.crates.io/crates/num-bigint/num-bigint-0.4.3.crate"
}
- version: "0.4.2"
+ version: "0.4.3"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 9
- day: 22
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/RELEASES.md b/RELEASES.md
index b06f4fa..cd1432f 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -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]
@@ -37,6 +46,12 @@
[194]: https://github.com/rust-num/num-bigint/pull/194
[195]: https://github.com/rust-num/num-bigint/pull/195
+# Release 0.3.3 (2021-09-03)
+
+- [Use explicit `Integer::div_ceil` to avoid the new unstable method.][219]
+
+**Contributors**: @catenacyber, @cuviper
+
# Release 0.3.2 (2021-03-04)
- [The new `BigUint` methods `count_ones` and `trailing_ones`][175] return the
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a82f7e0..8088cd8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -34,6 +34,9 @@
"name": "num-bigint_test_tests_biguint_scalar"
},
{
+ "name": "num-bigint_test_tests_fuzzed"
+ },
+ {
"name": "num-bigint_test_tests_modpow"
},
{
@@ -69,6 +72,9 @@
"name": "num-bigint_test_tests_biguint_scalar"
},
{
+ "name": "num-bigint_test_tests_fuzzed"
+ },
+ {
"name": "num-bigint_test_tests_modpow"
},
{
diff --git a/out/probe0.ll b/out/probe0.ll
index 296297c..75980c5 100644
--- a/out/probe0.ll
+++ b/out/probe0.ll
@@ -1,5 +1,5 @@
-; ModuleID = 'probe0.3041c4be-cgu.0'
-source_filename = "probe0.3041c4be-cgu.0"
+; ModuleID = 'probe0.990c8f4d-cgu.0'
+source_filename = "probe0.990c8f4d-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/out/probe1.ll b/out/probe1.ll
index dd4e8ea..c92f43c 100644
--- a/out/probe1.ll
+++ b/out/probe1.ll
@@ -1,5 +1,5 @@
-; ModuleID = 'probe1.56ebf6f4-cgu.0'
-source_filename = "probe1.56ebf6f4-cgu.0"
+; ModuleID = 'probe1.84fcdf3f-cgu.0'
+source_filename = "probe1.84fcdf3f-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/out/probe2.ll b/out/probe2.ll
index a93303e..a286ca1 100644
--- a/out/probe2.ll
+++ b/out/probe2.ll
@@ -1,5 +1,5 @@
-; ModuleID = 'probe2.a8400cd7-cgu.0'
-source_filename = "probe2.a8400cd7-cgu.0"
+; ModuleID = 'probe2.c1d38c83-cgu.0'
+source_filename = "probe2.c1d38c83-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/out/probe3.ll b/out/probe3.ll
index c0660f8..48c0ad3 100644
--- a/out/probe3.ll
+++ b/out/probe3.ll
@@ -1,5 +1,5 @@
-; ModuleID = 'probe3.474510b1-cgu.0'
-source_filename = "probe3.474510b1-cgu.0"
+; ModuleID = 'probe3.4a60c962-cgu.0'
+source_filename = "probe3.4a60c962-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
diff --git a/src/biguint/multiplication.rs b/src/biguint/multiplication.rs
index 581c9e1..597a202 100644
--- a/src/biguint/multiplication.rs
+++ b/src/biguint/multiplication.rs
@@ -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;
@@ -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
@@ -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);
diff --git a/tests/biguint.rs b/tests/biguint.rs
index 5a5979c..821b754 100644
--- a/tests/biguint.rs
+++ b/tests/biguint.rs
@@ -1008,13 +1008,27 @@ 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() {
let (a_vec, b_vec, c_vec) = *elm;
diff --git a/tests/fuzzed.rs b/tests/fuzzed.rs
new file mode 100644
index 0000000..7ff5641
--- /dev/null
+++ b/tests/fuzzed.rs
@@ -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);
+}