Skip to content

Make Parse function non-recursive #68

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 6, 2021

Conversation

meshcollider
Copy link
Contributor

@meshcollider meshcollider commented Sep 23, 2021

Follow-on from #66

This makes Parse non-recursive too.

disclaimer: I haven't thoroughly tested this since rebasing so using the grammar again to test this thoroughly would be great.

@meshcollider meshcollider force-pushed the 202109_nonrecursive_parse_alone branch from 3fe3304 to 8e191ad Compare September 27, 2021 23:07
@meshcollider
Copy link
Contributor Author

Rebased and addressed @darosior's comment

@darosior
Copy link
Contributor

Sorry, my suggestion is outdated now. Let's wait until we settled on what should be in IsValid and IsSafe before i suggest a new change :)

@darosior darosior mentioned this pull request Sep 28, 2021
@sipa
Copy link
Owner

sipa commented Sep 29, 2021

Rebase?

@meshcollider meshcollider force-pushed the 202109_nonrecursive_parse_alone branch from 8a552e9 to 0d3594a Compare September 30, 2021 00:07
@meshcollider
Copy link
Contributor Author

Rebased 🙂

@sipa
Copy link
Owner

sipa commented Dec 2, 2021

Can I haz rerebase?

@meshcollider meshcollider force-pushed the 202109_nonrecursive_parse_alone branch 3 times, most recently from e4cf81a to 8196fb0 Compare December 3, 2021 00:18
@meshcollider
Copy link
Contributor Author

Rebased

@meshcollider meshcollider force-pushed the 202109_nonrecursive_parse_alone branch from 8196fb0 to dcaf9ac Compare December 4, 2021 04:48
@meshcollider
Copy link
Contributor Author

Done!

@meshcollider
Copy link
Contributor Author

Added a commit to just consume the input span directly rather than working with the iterator, and used the spanparsing::Const function rather than the custom StartsWith. Still passes all the tests but apologies for adding more to review.

@meshcollider meshcollider force-pushed the 202109_nonrecursive_parse_alone branch from 7e0d13b to 60879af Compare December 5, 2021 05:13
@meshcollider
Copy link
Contributor Author

Updated

} else if (Const("pk(", in)) {
Key key;
int key_size = FindNextChar(in, ')');
if (key_size < 1) return {};
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is technically making the rules somewhat stricter, in that before it it was possible to have a ctx that accepted empty strings as key expressions, while now they're unconditionally rejected. I don't think that's a problem, though.

@sipa
Copy link
Owner

sipa commented Dec 6, 2021

utACK 60879af

@sipa sipa merged commit 5dc233f into sipa:master Dec 6, 2021
@sipa
Copy link
Owner

sipa commented Dec 6, 2021

The changes here are now active on http://bitcoin.sipa.be/miniscript/.

@meshcollider meshcollider deleted the 202109_nonrecursive_parse_alone branch December 6, 2021 21:41
Copy link
Contributor

@darosior darosior left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from not checking the bounds on thresh(), the code looks good to me.

I've been fuzzing the new parsing function using a modified parse_descriptor fuzzing target overnight, with a corpus expanded using the previous parse function. So far i did not find any crash in parsing nor failure to roundtrip introduced here.
(I seeded the corpus with valid Miniscripts, which might explain why the fuzzer didn't find the thresh() regression..)

Comment on lines +1074 to +1081
} else if (Const("thresh(", in)) {
int next_comma = FindNextChar(in, ',');
if (next_comma < 1) return {};
if (!ParseInt64(std::string(in.begin(), in.begin() + next_comma), &k)) return {};
in = in.subspan(next_comma + 1);
// n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH
to_parse.emplace_back(ParseContext::THRESH, 1, k);
to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm looks like you would accept a k = 0?

Comment on lines +1197 to +1204
// Children are constructed in reverse order, so iterate from end to beginning
std::vector<NodeRef<Key>> subs;
for (int i = 0; i < n; ++i) {
subs.push_back(std::move(constructed.back()));
constructed.pop_back();
}
std::reverse(subs.begin(), subs.end());
constructed.push_back(MakeNodeRef<Key>(NodeType::THRESH, std::move(subs), k));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to check that k <= subs.size().

Comment on lines +1641 to +1642
auto ret = Parse<typename Ctx::Key>(span, ctx);
if (!ret) return {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

    auto ret = Parse<typename Ctx::Key>(span, ctx);
    if (!ret) return {};
    return ret;

Could just be

    return Parse<typename Ctx::Key>(span, ctx);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants