[libclang] Fix use-after-free bug when handling attributes indexing info.

When indexing a property with a getter/setter with attributes, the allocated memory
for AttrListInfo could get released before its destructor is run.

Fixes rdar://11113442.

llvm-svn: 153792
This commit is contained in:
Argyrios Kyrtzidis 2012-03-31 01:14:06 +00:00
parent 79c1baf6dd
commit 0dbe9b6015
3 changed files with 68 additions and 52 deletions

View File

@ -3,5 +3,15 @@
@property (retain) __attribute__((iboutletcollection(Foo))) Foo *prop; @property (retain) __attribute__((iboutletcollection(Foo))) Foo *prop;
@end @end
@interface I
-(id)prop __attribute__((annotate("anno")));
-(void)setProp:(id)p __attribute__((annotate("anno")));
@property (assign) id prop __attribute__((annotate("anno")));
@end
// RUN: c-index-test -index-file %s | FileCheck %s // RUN: c-index-test -index-file %s | FileCheck %s
// CHECK: <attribute>: attribute(iboutletcollection)= [IBOutletCollection=ObjCInterface] // CHECK: <attribute>: attribute(iboutletcollection)= [IBOutletCollection=ObjCInterface]
// CHECK: <attribute>: attribute(annotate)=anno
// CHECK: <getter>: kind: objc-instance-method | name: prop | {{.*}} <attribute>: attribute(annotate)=anno
// CHECK: <setter>: kind: objc-instance-method | name: setProp: | {{.*}} <attribute>: attribute(annotate)=anno

View File

@ -61,9 +61,9 @@ IBOutletCollectionInfo::IBOutletCollectionInfo(
IBCollInfo.objcClass = 0; IBCollInfo.objcClass = 0;
} }
AttrListInfo::AttrListInfo(const Decl *D, AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx)
IndexingContext &IdxCtx, : SA(IdxCtx), ref_cnt(0) {
ScratchAlloc &SA) : ref_cnt(0) {
if (!D->hasAttrs()) if (!D->hasAttrs())
return; return;
@ -113,19 +113,11 @@ AttrListInfo::AttrListInfo(const Decl *D,
CXAttrs.push_back(&Attrs[i]); CXAttrs.push_back(&Attrs[i]);
} }
AttrListInfo::AttrListInfo(const AttrListInfo &other) { IntrusiveRefCntPtr<AttrListInfo>
assert(other.ref_cnt == 0 && AttrListInfo::create(const Decl *D, IndexingContext &IdxCtx) {
"Should not copy an AttrListInfo that is ref-counted"); ScratchAlloc SA(IdxCtx);
ref_cnt = 0; AttrListInfo *attrs = SA.allocate<AttrListInfo>();
return new (attrs) AttrListInfo(D, IdxCtx);
Attrs = other.Attrs;
IBCollAttrs = other.IBCollAttrs;
for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i)
CXAttrs.push_back(&IBCollAttrs[i]);
for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
CXAttrs.push_back(&Attrs[i]);
} }
IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, IndexingContext::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
@ -281,9 +273,8 @@ bool IndexingContext::handleDecl(const NamedDecl *D,
DInfo.loc = getIndexLoc(Loc); DInfo.loc = getIndexLoc(Loc);
DInfo.isImplicit = D->isImplicit(); DInfo.isImplicit = D->isImplicit();
AttrListInfo AttrList(D, *this, SA); DInfo.attributes = DInfo.EntInfo.attributes;
DInfo.attributes = AttrList.getAttrs(); DInfo.numAttributes = DInfo.EntInfo.numAttributes;
DInfo.numAttributes = AttrList.getNumAttrs();
getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer); getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer);
DInfo.semanticContainer = &DInfo.SemanticContainer; DInfo.semanticContainer = &DInfo.SemanticContainer;
@ -443,9 +434,10 @@ bool IndexingContext::handleObjCProtocol(const ObjCProtocolDecl *D) {
} }
bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) { bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
ScratchAlloc SA(*this);
ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
EntityInfo ClassEntity; EntityInfo ClassEntity;
ScratchAlloc SA(*this);
const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
SourceLocation ClassLoc = D->getLocation(); SourceLocation ClassLoc = D->getLocation();
SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
@ -474,10 +466,11 @@ bool IndexingContext::handleObjCCategory(const ObjCCategoryDecl *D) {
} }
bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { bool IndexingContext::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
ScratchAlloc SA(*this);
const ObjCCategoryDecl *CatD = D->getCategoryDecl(); const ObjCCategoryDecl *CatD = D->getCategoryDecl();
ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
EntityInfo ClassEntity; EntityInfo ClassEntity;
ScratchAlloc SA(*this);
const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
SourceLocation ClassLoc = D->getLocation(); SourceLocation ClassLoc = D->getLocation();
SourceLocation CategoryLoc = D->getCategoryNameLoc(); SourceLocation CategoryLoc = D->getCategoryNameLoc();
@ -522,10 +515,11 @@ bool IndexingContext::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
} }
bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) { bool IndexingContext::handleObjCProperty(const ObjCPropertyDecl *D) {
ScratchAlloc SA(*this);
ObjCPropertyDeclInfo DInfo; ObjCPropertyDeclInfo DInfo;
EntityInfo GetterEntity; EntityInfo GetterEntity;
EntityInfo SetterEntity; EntityInfo SetterEntity;
ScratchAlloc SA(*this);
DInfo.ObjCPropDeclInfo.declInfo = &DInfo; DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
@ -846,11 +840,9 @@ void IndexingContext::getEntityInfo(const NamedDecl *D,
EntityInfo.lang = CXIdxEntityLang_C; EntityInfo.lang = CXIdxEntityLang_C;
if (D->hasAttrs()) { if (D->hasAttrs()) {
AttrListInfo *attrs = SA.allocate<AttrListInfo>(); EntityInfo.AttrList = AttrListInfo::create(D, *this);
new (attrs) AttrListInfo(D, *this, SA); EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
EntityInfo.AttrList = attrs; EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
EntityInfo.attributes = attrs->getAttrs();
EntityInfo.numAttributes = attrs->getNumAttrs();
} }
if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {

View File

@ -25,9 +25,24 @@ namespace clang {
namespace cxindex { namespace cxindex {
class IndexingContext; class IndexingContext;
class ScratchAlloc;
class AttrListInfo; class AttrListInfo;
class ScratchAlloc {
IndexingContext &IdxCtx;
public:
explicit ScratchAlloc(IndexingContext &indexCtx);
ScratchAlloc(const ScratchAlloc &SA);
~ScratchAlloc();
const char *toCStr(StringRef Str);
const char *copyCStr(StringRef Str);
template <typename T>
T *allocate();
};
struct EntityInfo : public CXIdxEntityInfo { struct EntityInfo : public CXIdxEntityInfo {
const NamedDecl *Dcl; const NamedDecl *Dcl;
IndexingContext *IndexCtx; IndexingContext *IndexCtx;
@ -229,16 +244,20 @@ struct IBOutletCollectionInfo : public AttrInfo {
}; };
class AttrListInfo { class AttrListInfo {
ScratchAlloc SA;
SmallVector<AttrInfo, 2> Attrs; SmallVector<AttrInfo, 2> Attrs;
SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs; SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
SmallVector<CXIdxAttrInfo *, 2> CXAttrs; SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
unsigned ref_cnt; unsigned ref_cnt;
AttrListInfo(const AttrListInfo&); // DO NOT IMPLEMENT
void operator=(const AttrListInfo&); // DO NOT IMPLEMENT
public: public:
AttrListInfo(const Decl *D, AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
IndexingContext &IdxCtx,
ScratchAlloc &SA); static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
AttrListInfo(const AttrListInfo &other); IndexingContext &IdxCtx);
const CXIdxAttrInfo *const *getAttrs() const { const CXIdxAttrInfo *const *getAttrs() const {
if (CXAttrs.empty()) if (CXAttrs.empty())
@ -488,28 +507,23 @@ private:
static bool shouldIgnoreIfImplicit(const Decl *D); static bool shouldIgnoreIfImplicit(const Decl *D);
}; };
class ScratchAlloc { inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
IndexingContext &IdxCtx; ++IdxCtx.StrAdapterCount;
}
inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
++IdxCtx.StrAdapterCount;
}
public: inline ScratchAlloc::~ScratchAlloc() {
explicit ScratchAlloc(IndexingContext &indexCtx) : IdxCtx(indexCtx) { --IdxCtx.StrAdapterCount;
++IdxCtx.StrAdapterCount; if (IdxCtx.StrAdapterCount == 0)
} IdxCtx.StrScratch.Reset();
}
~ScratchAlloc() { template <typename T>
--IdxCtx.StrAdapterCount; inline T *ScratchAlloc::allocate() {
if (IdxCtx.StrAdapterCount == 0) return IdxCtx.StrScratch.Allocate<T>();
IdxCtx.StrScratch.Reset(); }
}
const char *toCStr(StringRef Str);
const char *copyCStr(StringRef Str);
template <typename T>
T *allocate() {
return IdxCtx.StrScratch.Allocate<T>();
}
};
}} // end clang::cxindex }} // end clang::cxindex