forked from OSchip/llvm-project
[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:
parent
79c1baf6dd
commit
0dbe9b6015
|
@ -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
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue