Skip to content

Commit

Permalink
[objcmt] Fix a buffer overflow crash than can occur while modernizing…
Browse files Browse the repository at this point in the history
… enums.

Note that due to the nature of the crash it requires libgmalloc or asan for it to crash consistently.

rdar://19932927

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@275600 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
akyrtzi committed Jul 15, 2016
1 parent 753944f commit 2527e4e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 28 deletions.
44 changes: 17 additions & 27 deletions lib/ARCMigrate/ObjCMT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,23 +771,11 @@ static void rewriteToNSMacroDecl(ASTContext &Ctx,
ClassString += ", ";

ClassString += TypedefDcl->getIdentifier()->getName();
ClassString += ')';
SourceLocation EndLoc;
if (EnumDcl->getIntegerTypeSourceInfo()) {
TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo();
TypeLoc TLoc = TSourceInfo->getTypeLoc();
EndLoc = TLoc.getLocEnd();
const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc);
unsigned count = 0;
if (lbrace)
while (lbrace[count] != '{')
++count;
if (count > 0)
EndLoc = EndLoc.getLocWithOffset(count-1);
}
else
EndLoc = EnumDcl->getLocStart();
SourceRange R(EnumDcl->getLocStart(), EndLoc);
ClassString += ") ";
SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
if (EndLoc.isInvalid())
return;
CharSourceRange R = CharSourceRange::getCharRange(EnumDcl->getLocStart(), EndLoc);
commit.replace(R, ClassString);
// This is to remove spaces between '}' and typedef name.
SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
Expand Down Expand Up @@ -1900,18 +1888,20 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
if (++N == DEnd)
continue;
if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
if (++N != DEnd)
if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
// prefer typedef-follows-enum to enum-follows-typedef pattern.
if (migrateNSEnumDecl(Ctx, ED, TDF)) {
++D; ++D;
CacheObjCNSIntegerTypedefed(TD);
continue;
if (canModify(ED)) {
if (++N != DEnd)
if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
// prefer typedef-follows-enum to enum-follows-typedef pattern.
if (migrateNSEnumDecl(Ctx, ED, TDF)) {
++D; ++D;
CacheObjCNSIntegerTypedefed(TD);
continue;
}
}
if (migrateNSEnumDecl(Ctx, ED, TD)) {
++D;
continue;
}
if (migrateNSEnumDecl(Ctx, ED, TD)) {
++D;
continue;
}
}
CacheObjCNSIntegerTypedefed(TD);
Expand Down
14 changes: 14 additions & 0 deletions test/ARCMT/objcmt-ns-enum-crash.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -objcmt-migrate-ns-macros -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result

#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
typedef long NSInteger;

typedef enum : NSInteger {five} ApplicableEnum;

typedef unsigned long mytd;

#define MY_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
MY_ENUM(MyEnum, unsigned int, One);
14 changes: 14 additions & 0 deletions test/ARCMT/objcmt-ns-enum-crash.m.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -objcmt-migrate-ns-macros -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result

#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
typedef long NSInteger;

typedef NS_ENUM(NSInteger, ApplicableEnum) {five};

typedef unsigned long mytd;

#define MY_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
MY_ENUM(MyEnum, unsigned int, One);
2 changes: 1 addition & 1 deletion test/ARCMT/objcmt-ns-macros.m.result
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ typedef NS_ENUM(NSInteger, UIK) {
UIKTwo = 2,
};

typedef NS_ENUM(unsigned int, NSTickMarkPosition) {
typedef NS_ENUM(unsigned int, NSTickMarkPosition) {
NSTickMarkBelow = 0,
NSTickMarkAbove = 1,
NSTickMarkLeft = NSTickMarkAbove,
Expand Down

0 comments on commit 2527e4e

Please sign in to comment.