mirror of
https://github.com/intel/llvm.git
synced 2026-02-03 02:26:27 +08:00
[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
llvm-svn: 281383
This commit is contained in:
@@ -5877,7 +5877,8 @@ bool Parser::isFunctionDeclaratorIdentifierList() {
|
||||
// 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
|
||||
|
||||
@@ -344,9 +344,11 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
|
||||
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::parseObjCTypeArgsAndProtocolQualifiers(
|
||||
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::parseObjCTypeArgsAndProtocolQualifiers(
|
||||
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;
|
||||
|
||||
@@ -1539,6 +1539,8 @@ Parser::TryAnnotateName(bool IsAddressOfOperand,
|
||||
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::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext,
|
||||
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
|
||||
|
||||
40
clang/test/SemaObjC/crash-on-type-args-protocols.m
Normal file
40
clang/test/SemaObjC/crash-on-type-args-protocols.m
Normal file
@@ -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
|
||||
|
||||
@protocol P;
|
||||
@interface NSObject
|
||||
@end
|
||||
@protocol X
|
||||
@end
|
||||
@interface X : NSObject <X>
|
||||
@end
|
||||
|
||||
@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}}
|
||||
Reference in New Issue
Block a user