Browse Source

Don't keep stale pointers to LoopInfos.

CGLoopInfo was keeping pointers to parent loop LoopInfos, but when the loop info vector grew, it reallocated the storage and invalidated all of the parent pointers, causing use-after-free. Manage the lifetimes of the LoopInfos separately so that the pointers aren't stale.

Patch by Bevin Hansson.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@369259 91177308-0d34-0410-b5e6-96231b3b80d8
Aaron Ballman 6 years ago
parent
commit
e03316caa0
3 changed files with 24 additions and 7 deletions
  1. 6 5
      lib/CodeGen/CGLoopInfo.cpp
  2. 2 2
      lib/CodeGen/CGLoopInfo.h
  3. 16 0
      test/CodeGen/loop-info-asan.c

+ 6 - 5
lib/CodeGen/CGLoopInfo.cpp

@@ -563,8 +563,9 @@ void LoopInfo::finish() {
 
 
 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
 void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc,
                          const llvm::DebugLoc &EndLoc) {
                          const llvm::DebugLoc &EndLoc) {
-  Active.push_back(LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
-                            Active.empty() ? nullptr : &Active.back()));
+  Active.emplace_back(
+      new LoopInfo(Header, StagedAttrs, StartLoc, EndLoc,
+                   Active.empty() ? nullptr : Active.back().get()));
   // Clear the attributes so nested loops do not inherit them.
   // Clear the attributes so nested loops do not inherit them.
   StagedAttrs.clear();
   StagedAttrs.clear();
 }
 }
@@ -756,16 +757,16 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx,
 
 
 void LoopInfoStack::pop() {
 void LoopInfoStack::pop() {
   assert(!Active.empty() && "No active loops to pop");
   assert(!Active.empty() && "No active loops to pop");
-  Active.back().finish();
+  Active.back()->finish();
   Active.pop_back();
   Active.pop_back();
 }
 }
 
 
 void LoopInfoStack::InsertHelper(Instruction *I) const {
 void LoopInfoStack::InsertHelper(Instruction *I) const {
   if (I->mayReadOrWriteMemory()) {
   if (I->mayReadOrWriteMemory()) {
     SmallVector<Metadata *, 4> AccessGroups;
     SmallVector<Metadata *, 4> AccessGroups;
-    for (const LoopInfo &AL : Active) {
+    for (const auto &AL : Active) {
       // Here we assume that every loop that has an access group is parallel.
       // Here we assume that every loop that has an access group is parallel.
-      if (MDNode *Group = AL.getAccessGroup())
+      if (MDNode *Group = AL->getAccessGroup())
         AccessGroups.push_back(Group);
         AccessGroups.push_back(Group);
     }
     }
     MDNode *UnionMD = nullptr;
     MDNode *UnionMD = nullptr;

+ 2 - 2
lib/CodeGen/CGLoopInfo.h

@@ -275,11 +275,11 @@ private:
   bool hasInfo() const { return !Active.empty(); }
   bool hasInfo() const { return !Active.empty(); }
   /// Return the LoopInfo for the current loop. HasInfo should be called
   /// Return the LoopInfo for the current loop. HasInfo should be called
   /// first to ensure LoopInfo is present.
   /// first to ensure LoopInfo is present.
-  const LoopInfo &getInfo() const { return Active.back(); }
+  const LoopInfo &getInfo() const { return *Active.back(); }
   /// The set of attributes that will be applied to the next pushed loop.
   /// The set of attributes that will be applied to the next pushed loop.
   LoopAttributes StagedAttrs;
   LoopAttributes StagedAttrs;
   /// Stack of active loops.
   /// Stack of active loops.
-  llvm::SmallVector<LoopInfo, 4> Active;
+  llvm::SmallVector<std::unique_ptr<LoopInfo>, 4> Active;
 };
 };
 
 
 } // end namespace CodeGen
 } // end namespace CodeGen

+ 16 - 0
test/CodeGen/loop-info-asan.c

@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o /dev/null
+
+// This test should not exhibit use-after-free in LoopInfo.
+
+int a() {
+  for (;;)
+    for (;;)
+      for (;;)
+        for (;;)
+          for (;;)
+            for (;;)
+              for (;;)
+                for (;;)
+                  for (;;)
+                    ;
+}