From: Alex Lorenz Date: Mon, 19 Jun 2017 17:53:21 +0000 (+0000) Subject: [Parser][ObjC] Use an artificial EOF token while parsing lexed ObjC methods X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a29f3b4c8d5c9042103398f643bf8b32a5d9974;p=clang [Parser][ObjC] Use an artificial EOF token while parsing lexed ObjC methods This change avoid a crash that occurred when skipping to EOF while parsing an ObjC interface/implementation. rdar://31963299 Differential Revision: https://reviews.llvm.org/D34185 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305719 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 77e63efc06..caa6323d32 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -3627,6 +3627,14 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { SourceLocation OrigLoc = Tok.getLocation(); assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!"); + // Store an artificial EOF token to ensure that we don't run off the end of + // the method's body when we come to parse it. + Token Eof; + Eof.startToken(); + Eof.setKind(tok::eof); + Eof.setEofData(MCDecl); + Eof.setLocation(OrigLoc); + LM.Toks.push_back(Eof); // Append the current token at the end of the new token stream so that it // doesn't get lost. LM.Toks.push_back(Tok); @@ -3658,7 +3666,7 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { Actions.ActOnDefaultCtorInitializers(MCDecl); ParseFunctionStatementBody(MCDecl, BodyScope); } - + if (Tok.getLocation() != OrigLoc) { // Due to parsing error, we either went over the cached tokens or // there are still cached tokens left. If it's the latter case skip the @@ -3670,4 +3678,6 @@ void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) { while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof)) ConsumeAnyToken(); } + // Clean up the remaining EOF token. + ConsumeAnyToken(); } diff --git a/test/Parser/objc-at-implementation-eof-crash.m b/test/Parser/objc-at-implementation-eof-crash.m new file mode 100644 index 0000000000..01469ecb11 --- /dev/null +++ b/test/Parser/objc-at-implementation-eof-crash.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify -Wno-objc-root-class %s + +@interface ClassA + +- (void)fileExistsAtPath:(int)x; + +@end + +@interface ClassB + +@end + +@implementation ClassB // expected-note {{implementation started here}} + +- (void) method:(ClassA *)mgr { // expected-note {{to match this '{'}} + mgr fileExistsAtPath:0 +} // expected-error {{expected ']'}} + +@implementation ClassC // expected-error {{missing '@end'}} // expected-error {{expected '}'}} // expected-warning {{cannot find interface declaration for 'ClassC'}} + +@end diff --git a/test/Parser/objc-at-interface-eof-crash.m b/test/Parser/objc-at-interface-eof-crash.m new file mode 100644 index 0000000000..7776838c9e --- /dev/null +++ b/test/Parser/objc-at-interface-eof-crash.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -verify -Wno-objc-root-class %s + +@interface ClassA + +- (void)fileExistsAtPath:(int)x; + +@end + +@interface ClassB + +@end + +@implementation ClassB // expected-note {{implementation started here}} + +- (void) method:(ClassA *)mgr { // expected-note {{to match this '{'}} + mgr fileExistsAtPath:0 +} // expected-error {{expected ']'}} + +@interface ClassC // expected-error {{missing '@end'}} // expected-error {{expected '}'}} + +@end