Skip to content
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

Nested ? matchers can cause the compiler to infinite loop/crash #57597

Closed
alercah opened this issue Jan 14, 2019 · 6 comments · Fixed by #57610
Closed

Nested ? matchers can cause the compiler to infinite loop/crash #57597

alercah opened this issue Jan 14, 2019 · 6 comments · Fixed by #57610
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.

Comments

@alercah
Copy link
Contributor

alercah commented Jan 14, 2019

The following code will cause the compiler to fail:

macro_rules! ex {
    ($($(i:ident)?)+) => { };
}

fn main() {
    ex!();
}

Playground link: https://play.rust-lang.org/?version=beta&mode=debug&edition=2018&gist=acce7614d74028b67c92a79b50b93522

It should error that the inner matcher can match an empty string and reject it, just as it does if * is used in place of ?.

@jonas-schievink
Copy link
Contributor

The fix should be very easy, since this was already fixed for * repetitions in #36721 (original bug: #5067):

match *seq_tt {
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
TokenTree::Sequence(_, ref sub_seq) =>
sub_seq.op == quoted::KleeneOp::ZeroOrMore,
_ => false,
}

Looks like sub_seq.op just needs to be checked against ?, too.

@Centril Centril added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. labels Jan 14, 2019
@Centril
Copy link
Contributor

Centril commented Jan 14, 2019

cc @mark-i-m

@alercah
Copy link
Contributor Author

alercah commented Jan 14, 2019

Note that with ? on the outside, this errors properly, although with inconsistent error messages: if the inner repetition uses * only, the error is "repetition matches empty token tree", but it seems that if any of the repetitions are ?, then the error is "multiple successful parses".

@Centril Centril added the I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. label Jan 14, 2019
@alercah
Copy link
Contributor Author

alercah commented Jan 14, 2019

The behaviour in my previous comment is because the check for "repetition matches empty token tree" is done at definition time, but does not catch $($($i:ident)*)?; this is caught at expansion time however. Ideally all of this will be moved to definition time and the expansion-time check should probably be a) corrected to address the first comment and b) possibly become an ICE, since it should never be encountered since the RFC 550 rules should eliminate all ambiguity at definition time?

@mark-i-m
Copy link
Member

Hmm... I don't really remember how most of this code works...

Just grepping, but it looks like there are a couple of other places we might want to look at:

// Reverse scan: Sequence comes before `first`.
if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore {
// If sequence is potentially empty, then
// union them (preserving first emptiness).
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
} else {
// Otherwise, sequence guaranteed
// non-empty; replace first.
first = subfirst;
}

if subfirst.maybe_empty ||
seq_rep.op == quoted::KleeneOp::ZeroOrMore {
// continue scanning for more first
// tokens, but also make sure we
// restore empty-tracking state
first.maybe_empty = true;
continue;
} else {
return first;
}
}

@mark-i-m
Copy link
Member

I've opened #57610

Centril added a commit to Centril/rust that referenced this issue Jan 17, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Centril added a commit to Centril/rust that referenced this issue Jan 17, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Centril added a commit to Centril/rust that referenced this issue Jan 17, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Centril added a commit to Centril/rust that referenced this issue Jan 18, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Centril added a commit to Centril/rust that referenced this issue Jan 18, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Centril added a commit to Centril/rust that referenced this issue Jan 19, 2019
…enkov

Fix nested `?` matchers

fix rust-lang#57597

I'm not 100% if this works yet...

cc @alercah

When  this is ready (but perhaps not yet):
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants