From b6ab533b93420e828ea6f555bc7d34d91cb07a34 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 19 Aug 2019 13:37:41 +0000 Subject: [PATCH] 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. llvm-svn: 369259 --- clang/lib/CodeGen/CGLoopInfo.cpp | 11 ++++++----- clang/lib/CodeGen/CGLoopInfo.h | 4 ++-- clang/test/CodeGen/loop-info-asan.c | 16 ++++++++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 clang/test/CodeGen/loop-info-asan.c diff --git a/clang/lib/CodeGen/CGLoopInfo.cpp b/clang/lib/CodeGen/CGLoopInfo.cpp index c51efdc5d111..6822c6286fef 100644 --- a/clang/lib/CodeGen/CGLoopInfo.cpp +++ b/clang/lib/CodeGen/CGLoopInfo.cpp @@ -563,8 +563,9 @@ void LoopInfo::finish() { void LoopInfoStack::push(BasicBlock *Header, const llvm::DebugLoc &StartLoc, 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. StagedAttrs.clear(); } @@ -756,16 +757,16 @@ void LoopInfoStack::push(BasicBlock *Header, clang::ASTContext &Ctx, void LoopInfoStack::pop() { assert(!Active.empty() && "No active loops to pop"); - Active.back().finish(); + Active.back()->finish(); Active.pop_back(); } void LoopInfoStack::InsertHelper(Instruction *I) const { if (I->mayReadOrWriteMemory()) { SmallVector AccessGroups; - for (const LoopInfo &AL : Active) { + for (const auto &AL : Active) { // 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); } MDNode *UnionMD = nullptr; diff --git a/clang/lib/CodeGen/CGLoopInfo.h b/clang/lib/CodeGen/CGLoopInfo.h index 31322c72136c..5abcf37c5433 100644 --- a/clang/lib/CodeGen/CGLoopInfo.h +++ b/clang/lib/CodeGen/CGLoopInfo.h @@ -275,11 +275,11 @@ private: bool hasInfo() const { return !Active.empty(); } /// Return the LoopInfo for the current loop. HasInfo should be called /// 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. LoopAttributes StagedAttrs; /// Stack of active loops. - llvm::SmallVector Active; + llvm::SmallVector, 4> Active; }; } // end namespace CodeGen diff --git a/clang/test/CodeGen/loop-info-asan.c b/clang/test/CodeGen/loop-info-asan.c new file mode 100644 index 000000000000..86bf40565acd --- /dev/null +++ b/clang/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 (;;) + ; +}