From df24b15e7264f982efcf72f4a4b61790afbc49f5 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Mon, 21 Nov 2016 11:16:30 +0000 Subject: [PATCH] [ObjC] Prevent infinite loops when iterating over redeclaration of a method that was declared in an invalid interface This commit fixes an infinite loop that occurs when clang tries to iterate over redeclaration of a method that was declared in an invalid @interface. The existing validity checks don't catch this as that @interface is a duplicate of a previously declared valid @interface declaration, so we have to verify that the found redeclaration is in a valid declaration context. rdar://29220965 Differential Revision: https://reviews.llvm.org/D26664 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@287530 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclObjC.cpp | 6 ++++++ .../method-redecls-invalid-interface.m | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 test/SemaObjC/method-redecls-invalid-interface.m diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 72e0fcea7b..60d05f682e 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -870,6 +870,12 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() { } } + // Ensure that the discovered method redeclaration has a valid declaration + // context. Used to prevent infinite loops when iterating redeclarations in + // a partially invalid AST. + if (Redecl && cast(Redecl->getDeclContext())->isInvalidDecl()) + Redecl = nullptr; + if (!Redecl && isRedeclaration()) { // This is the last redeclaration, go back to the first method. return cast(CtxD)->getMethod(getSelector(), diff --git a/test/SemaObjC/method-redecls-invalid-interface.m b/test/SemaObjC/method-redecls-invalid-interface.m new file mode 100644 index 0000000000..235d6fe5e9 --- /dev/null +++ b/test/SemaObjC/method-redecls-invalid-interface.m @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wdocumentation -Wno-objc-root-class %s +// rdar://29220965 + +@interface InvalidInterface { // expected-note {{previous definition is here}} + int *_property; +} + +@end + +/*! + */ + +@interface InvalidInterface // expected-error {{duplicate interface definition for class 'InvalidInterface'}} +@property int *property; + +-(void) method; +@end + +@implementation InvalidInterface +-(void) method { } +@end -- 2.40.0