|
4 | 4 |
|
5 | 5 | #include <test/fuzz/util/descriptor.h>
|
6 | 6 |
|
| 7 | +#include <ranges> |
7 | 8 | #include <stack>
|
8 | 9 |
|
9 | 10 | void MockedDescriptorConverter::Init() {
|
@@ -110,3 +111,35 @@ bool HasTooManySubFrag(const FuzzBufferType& buff, const int max_subs, const siz
|
110 | 111 | }
|
111 | 112 | return false;
|
112 | 113 | }
|
| 114 | + |
| 115 | +bool HasTooManyWrappers(const FuzzBufferType& buff, const int max_wrappers) |
| 116 | +{ |
| 117 | + // The number of nested wrappers. Nested wrappers are always characters which follow each other so we don't have to |
| 118 | + // use a stack as we do above when counting the number of sub-fragments. |
| 119 | + std::optional<int> count; |
| 120 | + |
| 121 | + // We want to detect nested wrappers. A wrapper is a character prepended to a fragment, separated by a colon. There |
| 122 | + // may be more than one wrapper, in which case the colon is not repeated. For instance `jjjjj:pk()`. To count |
| 123 | + // wrappers we iterate in reverse and use the colon to detect the end of a wrapper expression and count how many |
| 124 | + // characters there are since the beginning of the expression. We stop counting when we encounter a character |
| 125 | + // indicating the beginning of a new expression. |
| 126 | + for (const auto ch: buff | std::views::reverse) { |
| 127 | + // A colon, start counting. |
| 128 | + if (ch == ':') { |
| 129 | + // The colon itself is not a wrapper so we start at 0. |
| 130 | + count = 0; |
| 131 | + } else if (count) { |
| 132 | + // If we are counting wrappers, stop when we crossed the beginning of the wrapper expression. Otherwise keep |
| 133 | + // counting and bail if we reached the limit. |
| 134 | + // A wrapper may only ever occur as the first sub of a descriptor/miniscript expression ('('), as the |
| 135 | + // first Taproot leaf in a pair ('{') or as the nth sub in each case (','). |
| 136 | + if (ch == ',' || ch == '(' || ch == '{') { |
| 137 | + count.reset(); |
| 138 | + } else if (++*count > max_wrappers) { |
| 139 | + return true; |
| 140 | + } |
| 141 | + } |
| 142 | + } |
| 143 | + |
| 144 | + return false; |
| 145 | +} |
0 commit comments