Author: rsmith Date: Mon Nov 30 19:10:48 2015 New Revision: 254359 URL: http://llvm.org/viewvc/llvm-project?rev=254359&view=rev Log: Fix use-after-free when a C++ thread_local variable gets replaced (because its type changes when the initializer is attached). Don't hold onto the GlobalVariable*; recompute it from the VarDecl* instead.
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h cfe/trunk/lib/CodeGen/CGDeclCXX.cpp cfe/trunk/lib/CodeGen/CodeGenModule.cpp cfe/trunk/lib/CodeGen/CodeGenModule.h cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original) +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Mon Nov 30 19:10:48 2015 @@ -538,11 +538,9 @@ public: /// thread_local variables, a list of functions to perform the /// initialization. virtual void EmitThreadLocalInitFuncs( - CodeGenModule &CGM, - ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>> - CXXThreadLocals, + CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) = 0; + ArrayRef<const VarDecl *> CXXThreadLocalInitVars) = 0; // Determine if references to thread_local global variables can be made // directly or require access through a thread wrapper function. Modified: cfe/trunk/lib/CodeGen/CGDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDeclCXX.cpp?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDeclCXX.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDeclCXX.cpp Mon Nov 30 19:10:48 2015 @@ -337,7 +337,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitF // FIXME: We only need to register one __cxa_thread_atexit function for the // entire TU. CXXThreadLocalInits.push_back(Fn); - CXXThreadLocalInitVars.push_back(Addr); + CXXThreadLocalInitVars.push_back(D); } else if (PerformInit && ISA) { EmitPointerToInitFunc(D, Addr, Fn, ISA); } else if (auto *IPA = D->getAttr<InitPriorityAttr>()) { Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Nov 30 19:10:48 2015 @@ -1986,7 +1986,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(Str if (D->getTLSKind()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) - CXXThreadLocals.push_back(std::make_pair(D, GV)); + CXXThreadLocals.push_back(D); setTLSMode(GV, *D); } @@ -2379,7 +2379,7 @@ void CodeGenModule::EmitGlobalVarDefinit if (D->getTLSKind() && !GV->isThreadLocal()) { if (D->getTLSKind() == VarDecl::TLS_Dynamic) - CXXThreadLocals.push_back(std::make_pair(D, GV)); + CXXThreadLocals.push_back(D); setTLSMode(GV, *D); } Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original) +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Mon Nov 30 19:10:48 2015 @@ -378,13 +378,12 @@ private: StaticExternCMap StaticExternCValues; /// \brief thread_local variables defined or used in this TU. - std::vector<std::pair<const VarDecl *, llvm::GlobalVariable *> > - CXXThreadLocals; + std::vector<const VarDecl *> CXXThreadLocals; /// \brief thread_local variables with initializers that need to run /// before any thread_local variable in this TU is odr-used. std::vector<llvm::Function *> CXXThreadLocalInits; - std::vector<llvm::GlobalVariable *> CXXThreadLocalInitVars; + std::vector<const VarDecl *> CXXThreadLocalInitVars; /// Global variables with initializers that need to run before main. std::vector<llvm::Function *> CXXGlobalInits; Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Mon Nov 30 19:10:48 2015 @@ -327,10 +327,9 @@ public: llvm::Value *Val); void EmitThreadLocalInitFuncs( CodeGenModule &CGM, - ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>> - CXXThreadLocals, + ArrayRef<const VarDecl *> CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override; + ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; bool usesThreadWrapperFunction() const override { return true; } LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, @@ -2200,10 +2199,9 @@ ItaniumCXXABI::getOrCreateThreadLocalWra } void ItaniumCXXABI::EmitThreadLocalInitFuncs( - CodeGenModule &CGM, - ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>> - CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) { + CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, + ArrayRef<llvm::Function *> CXXThreadLocalInits, + ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { llvm::Function *InitFunc = nullptr; if (!CXXThreadLocalInits.empty()) { // Generate a guarded initialization function. @@ -2226,9 +2224,9 @@ void ItaniumCXXABI::EmitThreadLocalInitF .GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits, Address(Guard, GuardAlign)); } - for (auto &I : CXXThreadLocals) { - const VarDecl *VD = I.first; - llvm::GlobalVariable *Var = I.second; + for (const VarDecl *VD : CXXThreadLocals) { + llvm::GlobalVariable *Var = + cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD))); // Some targets require that all access to thread local variables go through // the thread wrapper. This means that we cannot attempt to create a thread @@ -2305,9 +2303,7 @@ void ItaniumCXXABI::EmitThreadLocalInitF LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType) { - QualType T = VD->getType(); - llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T); - llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty); + llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD); llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val); Val = CGF.Builder.CreateCall(Wrapper); Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original) +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Mon Nov 30 19:10:48 2015 @@ -377,11 +377,9 @@ public: const ReturnAdjustment &RA) override; void EmitThreadLocalInitFuncs( - CodeGenModule &CGM, - ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>> - CXXThreadLocals, + CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override; + ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override; bool usesThreadWrapperFunction() const override { return false; } LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, @@ -2197,11 +2195,9 @@ void MicrosoftCXXABI::registerGlobalDtor } void MicrosoftCXXABI::EmitThreadLocalInitFuncs( - CodeGenModule &CGM, - ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>> - CXXThreadLocals, + CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits, - ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) { + ArrayRef<const VarDecl *> CXXThreadLocalInitVars) { // This will create a GV in the .CRT$XDU section. It will point to our // initialization function. The CRT will call all of these function // pointers at start-up time and, eventually, at thread-creation time. @@ -2219,7 +2215,8 @@ void MicrosoftCXXABI::EmitThreadLocalIni std::vector<llvm::Function *> NonComdatInits; for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) { - llvm::GlobalVariable *GV = CXXThreadLocalInitVars[I]; + llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>( + CGM.GetGlobalValue(CGM.getMangledName(CXXThreadLocalInitVars[I]))); llvm::Function *F = CXXThreadLocalInits[I]; // If the GV is already in a comdat group, then we have to join it. Modified: cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp?rev=254359&r1=254358&r2=254359&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx11-thread-local.cpp Mon Nov 30 19:10:48 2015 @@ -20,6 +20,18 @@ struct U { static thread_local int m; }; // DARWIN: @_ZN1U1mE = internal thread_local global i32 0 thread_local int U::m = f(); +namespace MismatchedInitType { + // Check that we don't crash here when we're forced to create a new global + // variable (with a different type) when we add the initializer. + union U { + int a; + float f; + constexpr U() : f(0.0) {} + }; + static thread_local U u; + void *p = &u; +} + template<typename T> struct V { static thread_local int m; }; template<typename T> thread_local int V<T>::m = g(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits