Validate Microsoft's uuid attribute string.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122220 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index cfa2ab6..b616cd9 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -929,6 +929,8 @@
"'%0' attribute parameter %1 is out of bounds">;
def err_attribute_requires_objc_interface : Error<
"attribute may only be applied to an Objective-C interface">;
+def err_attribute_uuid_malformed_guid : Error<
+ "uuid attribute contains a malformed GUID">;
def warn_nonnull_pointers_only : Warning<
"nonnull attribute only applies to pointer arguments">;
def err_attribute_invalid_implicit_this_argument : Error<
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index b0e022f..e77a660 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2533,12 +2533,50 @@
}
Expr *Arg = Attr.getArg(0);
StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+ if (Str == 0 || Str->isWide()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ << "uuid" << 1;
+ return;
+ }
+
+ llvm::StringRef StrRef = Str->getString();
+
+ bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' &&
+ StrRef.back() == '}';
+
+ // Validate GUID length.
+ if (IsCurly && StrRef.size() != 38) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ if (!IsCurly && StrRef.size() != 36) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+
+ // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or
+ // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"
+ llvm::StringRef::iterator I = StrRef.begin();
+ if (IsCurly) // Skip the optional '{'
+ ++I;
+
+ for (int i = 0; i < 36; ++i) {
+ if (i == 8 || i == 13 || i == 18 || i == 23) {
+ if (*I != '-') {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ } else if (!isxdigit(*I)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid);
+ return;
+ }
+ I++;
+ }
d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context,
Str->getString()));
- } else {
+ } else
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid";
- }
}
//===----------------------------------------------------------------------===//
diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c
index 6c14742..98c8625 100644
--- a/test/Parser/MicrosoftExtensions.c
+++ b/test/Parser/MicrosoftExtensions.c
@@ -55,8 +55,16 @@
unsigned short Data3;
unsigned char Data4[8];
} GUID;
+
+struct __declspec(uuid(L"00000000-0000-0000-1234-000000000047")) uuid_attr_bad1 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}}
+struct __declspec(uuid(3)) uuid_attr_bad2 { };// expected-error {{'uuid' attribute requires parameter 1 to be a string}}
+struct __declspec(uuid("0000000-0000-0000-1234-0000500000047")) uuid_attr_bad3 { };// expected-error {{uuid attribute contains a malformed GUID}}
+struct __declspec(uuid("0000000-0000-0000-Z234-000000000047")) uuid_attr_bad4 { };// expected-error {{uuid attribute contains a malformed GUID}}
+struct __declspec(uuid("000000000000-0000-1234-000000000047")) uuid_attr_bad5 { };// expected-error {{uuid attribute contains a malformed GUID}}
+
+
struct __declspec(uuid("00000000-0000-0000-3231-000000000046")) A { };
-struct __declspec(uuid("00000000-0000-0000-1234-000000000047")) B { };
+struct __declspec(uuid("{00000000-0000-0000-1234-000000000047}")) B { };
class C {};
void uuidof_test2()