Add fuzzing harness for miniscript::FromScript(...)
.
Based on sipa’s PR #16800 (rebased on current master
).
Testing this PR
Run:
0$ CC=clang CXX=clang++ ./configure --enable-fuzz \
1 --with-sanitizers=address,fuzzer,undefined
2$ make
3$ src/test/fuzz/from_script -max_len=3
4…
5==1011==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000007d30 at pc
6 0x564149ae8922 bp 0x7ffdc121bb90 sp 0x7ffdc121b340
7…
8$ src/test/fuzz/from_script -max_len=3
9…
10from_script: script/miniscript.cpp:51: miniscript::Type
11 miniscript::internal::ComputeType(miniscript::NodeType, miniscript::Type,
12 miniscript::Type, miniscript::Type, const std::vector<Type> &, uint32_t, size_t,
13 size_t, size_t): Assertion `k > 1 && k < n_subs' failed.
14…
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:
0diff --git a/src/script/miniscript.h b/src/script/miniscript.h
1index d5bc80f98..9bd3f8426 100644
2--- a/src/script/miniscript.h
3+++ b/src/script/miniscript.h
4@@ -912,6 +912,9 @@ inline NodeRef<Key> DecodeSingle(I& in, I last, const Ctx& ctx) {
5 }
6 subs.clear();
7 if (last - in >= 3 && in[0].first == OP_EQUAL && ParseScriptNumber(in[1], k)) {
8+ if (k < 2) {
9+ return {};
10+ }
11 in += 2;
12 while (last - in >= 2 && in[0].first == OP_ADD) {
13 ++in;
14@@ -922,6 +925,9 @@ inline NodeRef<Key> DecodeSingle(I& in, I last, const Ctx& ctx) {
15 auto sub = DecodeSingle<Key>(in, last, ctx);
16 if (!sub) return {};
17 subs.push_back(std::move(sub));
18+ if (k >= subs.size()) {
19+ return {};
20+ }
21 std::reverse(subs.begin(), subs.end());
22 return MakeNodeRef<Key>(NodeType::THRESH, std::move(subs), k);
23 }