r269869 - Fix use-after-free ASan failures for modules / PCH files that deserialize abi_tag or no_sanitize attributes.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue May 17 17:16:51 PDT 2016


Author: rsmith
Date: Tue May 17 19:16:51 2016
New Revision: 269869

URL: http://llvm.org/viewvc/llvm-project?rev=269869&view=rev
Log:
Fix use-after-free ASan failures for modules / PCH files that deserialize abi_tag or no_sanitize attributes.

Modified:
    cfe/trunk/test/PCH/attrs.c
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/test/PCH/attrs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/attrs.c?rev=269869&r1=269868&r2=269869&view=diff
==============================================================================
--- cfe/trunk/test/PCH/attrs.c (original)
+++ cfe/trunk/test/PCH/attrs.c Tue May 17 19:16:51 2016
@@ -9,10 +9,12 @@
 #define HEADER
 
 int f(int) __attribute__((visibility("default"), overloadable));
+int g(int) __attribute__((abi_tag("foo", "bar", "baz"), no_sanitize("address", "memory"))); // expected-warning {{ignored}}
 
 #else
 
 double f(double); // expected-error{{overloadable}}
                   // expected-note at 11{{previous overload}}
+void h() { g(0); }
 
 #endif

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=269869&r1=269868&r2=269869&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Tue May 17 19:16:51 2016
@@ -98,6 +98,13 @@ static std::string ReadPCHRecord(StringR
     .Default("Record[Idx++]");
 }
 
+// Get a type that is suitable for storing an object of the specified type.
+static StringRef getStorageType(StringRef type) {
+  return StringSwitch<StringRef>(type)
+    .Case("StringRef", "std::string")
+    .Default(type);
+}
+
 // Assumes that the way to get the value is SA->getname()
 static std::string WritePCHRecord(StringRef type, StringRef name) {
   return "Record." + StringSwitch<std::string>(type)
@@ -644,15 +651,34 @@ namespace {
     }
 
     void writePCHReadDecls(raw_ostream &OS) const override {
-      OS << "  unsigned " << getLowerName() << "Size = Record[Idx++];\n";
-      OS << "  SmallVector<" << Type << ", 4> " << getLowerName()
-         << ";\n";
-      OS << "  " << getLowerName() << ".reserve(" << getLowerName()
+      OS << "    unsigned " << getLowerName() << "Size = Record[Idx++];\n";
+      OS << "    SmallVector<" << getType() << ", 4> "
+         << getLowerName() << ";\n";
+      OS << "    " << getLowerName() << ".reserve(" << getLowerName()
          << "Size);\n";
-      OS << "    for (unsigned i = " << getLowerName() << "Size; i; --i)\n";
-      
+
+      // If we can't store the values in the current type (if it's something
+      // like StringRef), store them in a different type and convert the
+      // container afterwards.
+      std::string StorageType = getStorageType(getType());
+      std::string StorageName = getLowerName();
+      if (StorageType != getType()) {
+        StorageName += "Storage";
+        OS << "    SmallVector<" << StorageType << ", 4> "
+           << StorageName << ";\n";
+        OS << "    " << StorageName << ".reserve(" << getLowerName()
+           << "Size);\n";
+      }
+
+      OS << "    for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";
       std::string read = ReadPCHRecord(Type);
-      OS << "    " << getLowerName() << ".push_back(" << read << ");\n";
+      OS << "      " << StorageName << ".push_back(" << read << ");\n";
+
+      if (StorageType != getType()) {
+        OS << "    for (unsigned i = 0; i != " << getLowerName() << "Size; ++i)\n";
+        OS << "      " << getLowerName() << ".push_back("
+           << StorageName << "[i]);\n";
+      }
     }
 
     void writePCHReadArgs(raw_ostream &OS) const override {




More information about the cfe-commits mailing list