arphaman created this revision.

This patch fixes a Clang crash that happens when an Objective-C source code 
contains an `@interface`/`@implementation` declaration that follows 
unterminated `@implementation` declaration that contains a method with a 
message send that doesn't have the ']'. The crash happens because the 
`@interface`/`@implementation` parsing methods encounter an unexpected EOF that 
is caused by parser's attempt to recover from the missing ']' by skipping to 
the next ']'/';' (it reaches EOF instead since these tokens are not present).


Repository:
  rL LLVM

https://reviews.llvm.org/D34185

Files:
  lib/Parse/ParseObjc.cpp
  test/Parser/objc-at-implementation-eof-crash.m
  test/Parser/objc-at-interface-eof-crash.m


Index: test/Parser/objc-at-interface-eof-crash.m
===================================================================
--- /dev/null
+++ 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'}}
+
+@end // expected-error {{expected '}'}}
Index: test/Parser/objc-at-implementation-eof-crash.m
===================================================================
--- /dev/null
+++ 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'}}
+
+@end // expected-error {{expected '}'}}
Index: lib/Parse/ParseObjc.cpp
===================================================================
--- lib/Parse/ParseObjc.cpp
+++ lib/Parse/ParseObjc.cpp
@@ -217,6 +217,8 @@
   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
   CheckNestedObjCContexts(AtLoc);
+  if (isEofOrEom())
+    return nullptr;
   ConsumeToken(); // the "interface" identifier
 
   // Code completion after '@interface'.
@@ -2101,6 +2103,8 @@
   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
   CheckNestedObjCContexts(AtLoc);
+  if (isEofOrEom())
+    return nullptr;
   ConsumeToken(); // the "implementation" identifier
 
   // Code completion after '@implementation'.


Index: test/Parser/objc-at-interface-eof-crash.m
===================================================================
--- /dev/null
+++ 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'}}
+
+@end // expected-error {{expected '}'}}
Index: test/Parser/objc-at-implementation-eof-crash.m
===================================================================
--- /dev/null
+++ 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'}}
+
+@end // expected-error {{expected '}'}}
Index: lib/Parse/ParseObjc.cpp
===================================================================
--- lib/Parse/ParseObjc.cpp
+++ lib/Parse/ParseObjc.cpp
@@ -217,6 +217,8 @@
   assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
          "ParseObjCAtInterfaceDeclaration(): Expected @interface");
   CheckNestedObjCContexts(AtLoc);
+  if (isEofOrEom())
+    return nullptr;
   ConsumeToken(); // the "interface" identifier
 
   // Code completion after '@interface'.
@@ -2101,6 +2103,8 @@
   assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
          "ParseObjCAtImplementationDeclaration(): Expected @implementation");
   CheckNestedObjCContexts(AtLoc);
+  if (isEofOrEom())
+    return nullptr;
   ConsumeToken(); // the "implementation" identifier
 
   // Code completion after '@implementation'.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to