r281383 - [SemaObjC] Be more strict while parsing type arguments and protocols

Bruno Cardoso Lopes via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 13 13:04:36 PDT 2016


Author: bruno
Date: Tue Sep 13 15:04:35 2016
New Revision: 281383

URL: http://llvm.org/viewvc/llvm-project?rev=281383&view=rev
Log:
[SemaObjC] Be more strict while parsing type arguments and protocols

Fix a crash-on-invalid.

When parsing type arguments and protocols,
parseObjCTypeArgsOrProtocolQualifiers() calls ParseTypeName(), which tries to
find matching tokens for '[', '(', etc whenever they appear among potential
type names. If unmatched, ParseTypeName() yields a tok::eof token stream. This
leads to crashes since the parsing at this point is not expected to go beyond
the param list closing '>'.

Fix that by properly handling tok::eof in
parseObjCTypeArgsOrProtocolQualifiers() callers.

Differential Revision: https://reviews.llvm.org/D23852

rdar://problem/25063557

Added:
    cfe/trunk/test/SemaObjC/crash-on-type-args-protocols.m
Modified:
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Parse/Parser.cpp

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=281383&r1=281382&r2=281383&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Sep 13 15:04:35 2016
@@ -5877,7 +5877,8 @@ bool Parser::isFunctionDeclaratorIdentif
          // To handle this, we check to see if the token after the first
          // identifier is a "," or ")".  Only then do we parse it as an
          // identifier list.
-         && (NextToken().is(tok::comma) || NextToken().is(tok::r_paren));
+         && (!Tok.is(tok::eof) &&
+             (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));
 }
 
 /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=281383&r1=281382&r2=281383&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Tue Sep 13 15:04:35 2016
@@ -344,9 +344,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclar
           protocols, protocolLocs, EndProtoLoc,
           /*consumeLastToken=*/true,
           /*warnOnIncompleteProtocols=*/true);
+      if (Tok.is(tok::eof))
+        return nullptr;
     }
   }
-  
+
   // Next, we need to check for any protocol references.
   if (LAngleLoc.isValid()) {
     if (!ProtocolIdents.empty()) {
@@ -1814,6 +1816,8 @@ void Parser::parseObjCTypeArgsAndProtoco
                                         protocolRAngleLoc,
                                         consumeLastToken,
                                         /*warnOnIncompleteProtocols=*/false);
+  if (Tok.is(tok::eof)) // Nothing else to do here...
+    return;
 
   // An Objective-C object pointer followed by type arguments
   // can then be followed again by a set of protocol references, e.g.,
@@ -1862,6 +1866,9 @@ TypeResult Parser::parseObjCTypeArgsAndP
                                          protocols, protocolLocs,
                                          protocolRAngleLoc, consumeLastToken);
 
+  if (Tok.is(tok::eof))
+    return true; // Invalid type result.
+
   // Compute the location of the last token.
   if (consumeLastToken)
     endLoc = PrevTokLocation;

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=281383&r1=281382&r2=281383&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Sep 13 15:04:35 2016
@@ -1539,6 +1539,8 @@ Parser::TryAnnotateName(bool IsAddressOf
                                                    NewEndLoc);
       if (NewType.isUsable())
         Ty = NewType.get();
+      else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+        return ANK_Error;
     }
 
     Tok.setKind(tok::annot_typename);
@@ -1770,6 +1772,8 @@ bool Parser::TryAnnotateTypeOrScopeToken
                                                    NewEndLoc);
         if (NewType.isUsable())
           Ty = NewType.get();
+        else if (Tok.is(tok::eof)) // Nothing to do here, bail out...
+          return false;
       }
 
       // This is a typename. Replace the current token in-place with an

Added: cfe/trunk/test/SemaObjC/crash-on-type-args-protocols.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/crash-on-type-args-protocols.m?rev=281383&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/crash-on-type-args-protocols.m (added)
+++ cfe/trunk/test/SemaObjC/crash-on-type-args-protocols.m Tue Sep 13 15:04:35 2016
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -DFIRST -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DSECOND -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DTHIRD -fsyntax-only -verify %s
+// RUN: %clang_cc1 -DFOURTH -fsyntax-only -verify %s
+
+ at protocol P;
+ at interface NSObject
+ at end
+ at protocol X
+ at end
+ at interface X : NSObject <X>
+ at end
+
+ at class A;
+
+#ifdef FIRST
+id<X> F1(id<[P> v) { // expected-error {{expected a type}} // expected-error {{use of undeclared identifier 'P'}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+  return 0;
+}
+#endif
+
+#ifdef SECOND
+id<X> F2(id<P[X> v) { // expected-error {{unknown type name 'P'}} // expected-error {{unexpected interface name 'X': expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+  return 0;
+}
+#endif
+
+#ifdef THIRD
+id<X> F3(id<P, P *[> v) { // expected-error {{unknown type name 'P'}} // expected-error {{expected expression}} // expected-error {{use of undeclared identifier 'v'}} // expected-note {{to match this '('}}
+  return 0;
+}
+#endif
+
+#ifdef FOURTH
+id<X> F4(id<P, P *(> v { // expected-error {{unknown type name 'P'}} // expected-error {{expected ')'}} // expected-note {{to match this '('}} // expected-note {{to match this '('}}
+  return 0;
+}
+#endif
+
+// expected-error {{expected '>'}} // expected-error {{expected parameter declarator}} // expected-error {{expected ')'}} // expected-error {{expected function body after function declarator}}




More information about the cfe-commits mailing list