mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 20:26:05 +00:00
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. llvm-svn: 254359
This commit is contained in:
parent
21ed3b13bd
commit
5a99c49d2e
@ -538,11 +538,9 @@ public:
|
|||||||
/// thread_local variables, a list of functions to perform the
|
/// thread_local variables, a list of functions to perform the
|
||||||
/// initialization.
|
/// initialization.
|
||||||
virtual void EmitThreadLocalInitFuncs(
|
virtual void EmitThreadLocalInitFuncs(
|
||||||
CodeGenModule &CGM,
|
CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
|
||||||
ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
|
|
||||||
CXXThreadLocals,
|
|
||||||
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
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
|
// Determine if references to thread_local global variables can be made
|
||||||
// directly or require access through a thread wrapper function.
|
// directly or require access through a thread wrapper function.
|
||||||
|
@ -337,7 +337,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
|
|||||||
// FIXME: We only need to register one __cxa_thread_atexit function for the
|
// FIXME: We only need to register one __cxa_thread_atexit function for the
|
||||||
// entire TU.
|
// entire TU.
|
||||||
CXXThreadLocalInits.push_back(Fn);
|
CXXThreadLocalInits.push_back(Fn);
|
||||||
CXXThreadLocalInitVars.push_back(Addr);
|
CXXThreadLocalInitVars.push_back(D);
|
||||||
} else if (PerformInit && ISA) {
|
} else if (PerformInit && ISA) {
|
||||||
EmitPointerToInitFunc(D, Addr, Fn, ISA);
|
EmitPointerToInitFunc(D, Addr, Fn, ISA);
|
||||||
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
|
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
|
||||||
|
@ -1986,7 +1986,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
|
|||||||
|
|
||||||
if (D->getTLSKind()) {
|
if (D->getTLSKind()) {
|
||||||
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
|
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
|
||||||
CXXThreadLocals.push_back(std::make_pair(D, GV));
|
CXXThreadLocals.push_back(D);
|
||||||
setTLSMode(GV, *D);
|
setTLSMode(GV, *D);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2379,7 +2379,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
|
|||||||
|
|
||||||
if (D->getTLSKind() && !GV->isThreadLocal()) {
|
if (D->getTLSKind() && !GV->isThreadLocal()) {
|
||||||
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
|
if (D->getTLSKind() == VarDecl::TLS_Dynamic)
|
||||||
CXXThreadLocals.push_back(std::make_pair(D, GV));
|
CXXThreadLocals.push_back(D);
|
||||||
setTLSMode(GV, *D);
|
setTLSMode(GV, *D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,13 +378,12 @@ private:
|
|||||||
StaticExternCMap StaticExternCValues;
|
StaticExternCMap StaticExternCValues;
|
||||||
|
|
||||||
/// \brief thread_local variables defined or used in this TU.
|
/// \brief thread_local variables defined or used in this TU.
|
||||||
std::vector<std::pair<const VarDecl *, llvm::GlobalVariable *> >
|
std::vector<const VarDecl *> CXXThreadLocals;
|
||||||
CXXThreadLocals;
|
|
||||||
|
|
||||||
/// \brief thread_local variables with initializers that need to run
|
/// \brief thread_local variables with initializers that need to run
|
||||||
/// before any thread_local variable in this TU is odr-used.
|
/// before any thread_local variable in this TU is odr-used.
|
||||||
std::vector<llvm::Function *> CXXThreadLocalInits;
|
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.
|
/// Global variables with initializers that need to run before main.
|
||||||
std::vector<llvm::Function *> CXXGlobalInits;
|
std::vector<llvm::Function *> CXXGlobalInits;
|
||||||
|
@ -327,10 +327,9 @@ public:
|
|||||||
llvm::Value *Val);
|
llvm::Value *Val);
|
||||||
void EmitThreadLocalInitFuncs(
|
void EmitThreadLocalInitFuncs(
|
||||||
CodeGenModule &CGM,
|
CodeGenModule &CGM,
|
||||||
ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
|
ArrayRef<const VarDecl *> CXXThreadLocals,
|
||||||
CXXThreadLocals,
|
|
||||||
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
||||||
ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override;
|
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
|
||||||
|
|
||||||
bool usesThreadWrapperFunction() const override { return true; }
|
bool usesThreadWrapperFunction() const override { return true; }
|
||||||
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
|
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
|
||||||
@ -2200,10 +2199,9 @@ ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ItaniumCXXABI::EmitThreadLocalInitFuncs(
|
void ItaniumCXXABI::EmitThreadLocalInitFuncs(
|
||||||
CodeGenModule &CGM,
|
CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
|
||||||
ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
|
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
||||||
CXXThreadLocals, ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) {
|
||||||
ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) {
|
|
||||||
llvm::Function *InitFunc = nullptr;
|
llvm::Function *InitFunc = nullptr;
|
||||||
if (!CXXThreadLocalInits.empty()) {
|
if (!CXXThreadLocalInits.empty()) {
|
||||||
// Generate a guarded initialization function.
|
// Generate a guarded initialization function.
|
||||||
@ -2226,9 +2224,9 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
|
|||||||
.GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits,
|
.GenerateCXXGlobalInitFunc(InitFunc, CXXThreadLocalInits,
|
||||||
Address(Guard, GuardAlign));
|
Address(Guard, GuardAlign));
|
||||||
}
|
}
|
||||||
for (auto &I : CXXThreadLocals) {
|
for (const VarDecl *VD : CXXThreadLocals) {
|
||||||
const VarDecl *VD = I.first;
|
llvm::GlobalVariable *Var =
|
||||||
llvm::GlobalVariable *Var = I.second;
|
cast<llvm::GlobalVariable>(CGM.GetGlobalValue(CGM.getMangledName(VD)));
|
||||||
|
|
||||||
// Some targets require that all access to thread local variables go through
|
// 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
|
// the thread wrapper. This means that we cannot attempt to create a thread
|
||||||
@ -2305,9 +2303,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
|
|||||||
LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
|
LValue ItaniumCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF,
|
||||||
const VarDecl *VD,
|
const VarDecl *VD,
|
||||||
QualType LValType) {
|
QualType LValType) {
|
||||||
QualType T = VD->getType();
|
llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD);
|
||||||
llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T);
|
|
||||||
llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty);
|
|
||||||
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
|
llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Val);
|
||||||
|
|
||||||
Val = CGF.Builder.CreateCall(Wrapper);
|
Val = CGF.Builder.CreateCall(Wrapper);
|
||||||
|
@ -377,11 +377,9 @@ public:
|
|||||||
const ReturnAdjustment &RA) override;
|
const ReturnAdjustment &RA) override;
|
||||||
|
|
||||||
void EmitThreadLocalInitFuncs(
|
void EmitThreadLocalInitFuncs(
|
||||||
CodeGenModule &CGM,
|
CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
|
||||||
ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
|
|
||||||
CXXThreadLocals,
|
|
||||||
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
||||||
ArrayRef<llvm::GlobalVariable *> CXXThreadLocalInitVars) override;
|
ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
|
||||||
|
|
||||||
bool usesThreadWrapperFunction() const override { return false; }
|
bool usesThreadWrapperFunction() const override { return false; }
|
||||||
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
|
LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
|
||||||
@ -2197,11 +2195,9 @@ void MicrosoftCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
|
void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
|
||||||
CodeGenModule &CGM,
|
CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
|
||||||
ArrayRef<std::pair<const VarDecl *, llvm::GlobalVariable *>>
|
|
||||||
CXXThreadLocals,
|
|
||||||
ArrayRef<llvm::Function *> CXXThreadLocalInits,
|
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
|
// 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
|
// initialization function. The CRT will call all of these function
|
||||||
// pointers at start-up time and, eventually, at thread-creation time.
|
// pointers at start-up time and, eventually, at thread-creation time.
|
||||||
@ -2219,7 +2215,8 @@ void MicrosoftCXXABI::EmitThreadLocalInitFuncs(
|
|||||||
|
|
||||||
std::vector<llvm::Function *> NonComdatInits;
|
std::vector<llvm::Function *> NonComdatInits;
|
||||||
for (size_t I = 0, E = CXXThreadLocalInitVars.size(); I != E; ++I) {
|
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];
|
llvm::Function *F = CXXThreadLocalInits[I];
|
||||||
|
|
||||||
// If the GV is already in a comdat group, then we have to join it.
|
// If the GV is already in a comdat group, then we have to join it.
|
||||||
|
@ -20,6 +20,18 @@ struct U { static thread_local int m; };
|
|||||||
// DARWIN: @_ZN1U1mE = internal thread_local global i32 0
|
// DARWIN: @_ZN1U1mE = internal thread_local global i32 0
|
||||||
thread_local int U::m = f();
|
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> struct V { static thread_local int m; };
|
||||||
template<typename T> thread_local int V<T>::m = g();
|
template<typename T> thread_local int V<T>::m = g();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user