summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2016-07-15 19:22:34 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2016-07-15 19:22:34 +0000
commit88737a5aa5cca893b47206cd048fa781fa3fc4d7 (patch)
tree851cbadcee48f73d071d799811e5b05543e8f0cb
parent7f6484448121dc82f8080b0c95a675a2317ca32c (diff)
downloadbcm5719-llvm-88737a5aa5cca893b47206cd048fa781fa3fc4d7.tar.gz
bcm5719-llvm-88737a5aa5cca893b47206cd048fa781fa3fc4d7.zip
[objcmt] Fix a buffer overflow crash than can occur while modernizing enums.
Note that due to the nature of the crash it requires libgmalloc or asan for it to crash consistently. rdar://19932927 llvm-svn: 275600
-rw-r--r--clang/lib/ARCMigrate/ObjCMT.cpp44
-rw-r--r--clang/test/ARCMT/objcmt-ns-enum-crash.m14
-rw-r--r--clang/test/ARCMT/objcmt-ns-enum-crash.m.result14
-rw-r--r--clang/test/ARCMT/objcmt-ns-macros.m.result2
4 files changed, 46 insertions, 28 deletions
diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp
index 940a9c95f28..241a7246b62 100644
--- a/clang/lib/ARCMigrate/ObjCMT.cpp
+++ b/clang/lib/ARCMigrate/ObjCMT.cpp
@@ -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();
@@ -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);
diff --git a/clang/test/ARCMT/objcmt-ns-enum-crash.m b/clang/test/ARCMT/objcmt-ns-enum-crash.m
new file mode 100644
index 00000000000..7c9c708efae
--- /dev/null
+++ b/clang/test/ARCMT/objcmt-ns-enum-crash.m
@@ -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);
diff --git a/clang/test/ARCMT/objcmt-ns-enum-crash.m.result b/clang/test/ARCMT/objcmt-ns-enum-crash.m.result
new file mode 100644
index 00000000000..0a76e66ea21
--- /dev/null
+++ b/clang/test/ARCMT/objcmt-ns-enum-crash.m.result
@@ -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);
diff --git a/clang/test/ARCMT/objcmt-ns-macros.m.result b/clang/test/ARCMT/objcmt-ns-macros.m.result
index c4c40300ee6..01078277673 100644
--- a/clang/test/ARCMT/objcmt-ns-macros.m.result
+++ b/clang/test/ARCMT/objcmt-ns-macros.m.result
@@ -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,
OpenPOWER on IntegriCloud