test(miniscript): Prove avoidance of stack overflow

Can be tested through emptying the function body of ~Node() or replacing Clone() implementation with naive version:
```C++
Node<Key> Clone() const
{
    std::vector<Node> new_subs;
    new_subs.reserve(subs.size());
    for (const Node& child : subs) {
        new_subs.push_back(child.Clone());
    }
    return Node{internal::NoDupCheck{}, m_script_ctx, fragment, std::move(new_subs), keys, data, k};
}
```

Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
This commit is contained in:
Hodlinator 2025-06-25 14:17:14 +02:00
parent 198bbaee49
commit 964c44cdcd
No known key found for this signature in database

View File

@ -727,4 +727,25 @@ BOOST_AUTO_TEST_CASE(fixed_tests)
g_testdata.reset();
}
// Confirm that ~Node(), Node::Clone() and operator=(Node&&) are stack-safe.
BOOST_AUTO_TEST_CASE(node_deep_destruct)
{
using miniscript::internal::NoDupCheck;
using miniscript::Fragment;
using NodeU32 = miniscript::Node<uint32_t>;
constexpr auto ctx{miniscript::MiniscriptContext::P2WSH};
NodeU32 root{NoDupCheck{}, ctx, Fragment::JUST_1};
for (uint32_t i{0}; i < 200'000; ++i) {
root = NodeU32{NoDupCheck{}, ctx, Fragment::WRAP_S, Vector(std::move(root))};
}
BOOST_CHECK_EQUAL(root.ScriptSize(), 200'001);
auto clone{root.Clone()};
BOOST_CHECK_EQUAL(clone.ScriptSize(), root.ScriptSize());
clone = std::move(root);
}
BOOST_AUTO_TEST_SUITE_END()