Merge 82722b9ebab796f877930848c1893c0c866f0e5f on remote branch

Change-Id: I7a85f5e159ceb3ee8307f0de37aff0691bdaba2d
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 @@
     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 @@
     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 @@
     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 {
+    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 @@
   }
   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 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 @@
 
         // 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 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 @@
 #[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);
+}