aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Poinsot <darosior@protonmail.com>2024-04-11 16:08:01 +0200
committerglozow <gloriajzhao@gmail.com>2024-05-23 17:05:57 +0100
commitd9ef6cf934cbd8e9b2f8256de001ca44f74ad6e9 (patch)
treeee460a6cdc2f21a2d2607b9aa91809fd6d81e558
parente4859c82c7b848554b4e9d27c2f8b8615422528e (diff)
sign: don't assume we are parsing a sane Miniscript
The script provided for signature might be externally provided, for instance by way of 'finalizepsbt'. Therefore the script might be ill-crafted, so don't assume pubkeys are always 32 bytes. Thanks to Niklas for finding this. Github-Pull: #29853 Rebased-From: 4d8d21320eba54571ff63931509cd515c3e20339
-rw-r--r--src/script/sign.cpp2
-rw-r--r--src/test/script_tests.cpp24
2 files changed, 25 insertions, 1 deletions
diff --git a/src/script/sign.cpp b/src/script/sign.cpp
index 251a8420f7..d91a246d03 100644
--- a/src/script/sign.cpp
+++ b/src/script/sign.cpp
@@ -295,7 +295,7 @@ struct TapSatisfier: Satisfier<XOnlyPubKey> {
//! Conversion from a raw xonly public key.
template <typename I>
std::optional<XOnlyPubKey> FromPKBytes(I first, I last) const {
- CHECK_NONFATAL(last - first == 32);
+ if (last - first != 32) return {};
XOnlyPubKey pubkey;
std::copy(first, last, pubkey.begin());
return pubkey;
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index 624d0b2c12..50715e9a04 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -1276,6 +1276,30 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
BOOST_CHECK(combined.scriptSig == partial3c);
}
+/**
+ * Reproduction of an exception incorrectly raised when parsing a public key inside a TapMiniscript.
+ */
+BOOST_AUTO_TEST_CASE(sign_invalid_miniscript)
+{
+ FillableSigningProvider keystore;
+ SignatureData sig_data;
+ CMutableTransaction prev, curr;
+
+ // Create a Taproot output which contains a leaf in which a non-32 bytes push is used where a public key is expected
+ // by the Miniscript parser. This offending Script was found by the RPC fuzzer.
+ const auto invalid_pubkey{ParseHex("173d36c8c9c9c9ffffffffffff0200000000021e1e37373721361818181818181e1e1e1e19000000000000000000b19292929292926b006c9b9b9292")};
+ TaprootBuilder builder;
+ builder.Add(0, {invalid_pubkey}, 0xc0);
+ XOnlyPubKey nums{ParseHex("50929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0")};
+ builder.Finalize(nums);
+ prev.vout.emplace_back(0, GetScriptForDestination(builder.GetOutput()));
+ curr.vin.emplace_back(COutPoint{prev.GetHash(), 0});
+ sig_data.tr_spenddata = builder.GetSpendData();
+
+ // SignSignature can fail but it shouldn't raise an exception (nor crash).
+ BOOST_CHECK(!SignSignature(keystore, CTransaction(prev), curr, 0, SIGHASH_ALL, sig_data));
+}
+
BOOST_AUTO_TEST_CASE(script_standard_push)
{
ScriptError err;