Add fuzzing harness for miniscript::FromScript(...).
Based on sipa's PR #16800 (rebased on current master).
Testing this PR
Run:
$ CC=clang CXX=clang++ ./configure --enable-fuzz \
--with-sanitizers=address,fuzzer,undefined
$ make
$ src/test/fuzz/from_script -max_len=3
…
==1011==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000007d30 at pc
0x564149ae8922 bp 0x7ffdc121bb90 sp 0x7ffdc121b340
…
$ src/test/fuzz/from_script -max_len=3
…
from_script: script/miniscript.cpp:51: miniscript::Type
miniscript::internal::ComputeType(miniscript::NodeType, miniscript::Type,
miniscript::Type, miniscript::Type, const std::vector<Type> &, uint32_t, size_t,
size_t, size_t): Assertion `k > 1 && k < n_subs' failed.
…
The fix to those two issues demonstrated above was submitted a month ago to the upstream repo https://github.com/sipa/miniscript/pull/18 :)
Here is my suggested patch if you want to try the fuzzer against the fixed version:
diff --git a/src/script/miniscript.h b/src/script/miniscript.h
index d5bc80f98..9bd3f8426 100644
--- a/src/script/miniscript.h
+++ b/src/script/miniscript.h
@@ -912,6 +912,9 @@ inline NodeRef<Key> DecodeSingle(I& in, I last, const Ctx& ctx) {
}
subs.clear();
if (last - in >= 3 && in[0].first == OP_EQUAL && ParseScriptNumber(in[1], k)) {
+ if (k < 2) {
+ return {};
+ }
in += 2;
while (last - in >= 2 && in[0].first == OP_ADD) {
++in;
@@ -922,6 +925,9 @@ inline NodeRef<Key> DecodeSingle(I& in, I last, const Ctx& ctx) {
auto sub = DecodeSingle<Key>(in, last, ctx);
if (!sub) return {};
subs.push_back(std::move(sub));
+ if (k >= subs.size()) {
+ return {};
+ }
std::reverse(subs.begin(), subs.end());
return MakeNodeRef<Key>(NodeType::THRESH, std::move(subs), k);
}