mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-19 06:31:18 +00:00
[msan] Handle param-tls overflow.
ParamTLS (shadow for function arguments) is of limited size. This change makes all arguments that do not fit unpoisoned, and avoids writing past the end of a TLS buffer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220351 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ec4e924836
commit
61ed31cad7
@ -127,6 +127,10 @@ static const uint64_t kOriginOffset64 = 1ULL << 45;
|
|||||||
static const unsigned kMinOriginAlignment = 4;
|
static const unsigned kMinOriginAlignment = 4;
|
||||||
static const unsigned kShadowTLSAlignment = 8;
|
static const unsigned kShadowTLSAlignment = 8;
|
||||||
|
|
||||||
|
// These constants must be kept in sync with the ones in msan.h.
|
||||||
|
static const unsigned kParamTLSSize = 800;
|
||||||
|
static const unsigned kRetvalTLSSize = 800;
|
||||||
|
|
||||||
// Accesses sizes are powers of two: 1, 2, 4, 8.
|
// Accesses sizes are powers of two: 1, 2, 4, 8.
|
||||||
static const size_t kNumberOfAccessSizes = 4;
|
static const size_t kNumberOfAccessSizes = 4;
|
||||||
|
|
||||||
@ -356,7 +360,7 @@ void MemorySanitizer::initializeCallbacks(Module &M) {
|
|||||||
|
|
||||||
// Create globals.
|
// Create globals.
|
||||||
RetvalTLS = new GlobalVariable(
|
RetvalTLS = new GlobalVariable(
|
||||||
M, ArrayType::get(IRB.getInt64Ty(), 8), false,
|
M, ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8), false,
|
||||||
GlobalVariable::ExternalLinkage, nullptr, "__msan_retval_tls", nullptr,
|
GlobalVariable::ExternalLinkage, nullptr, "__msan_retval_tls", nullptr,
|
||||||
GlobalVariable::InitialExecTLSModel);
|
GlobalVariable::InitialExecTLSModel);
|
||||||
RetvalOriginTLS = new GlobalVariable(
|
RetvalOriginTLS = new GlobalVariable(
|
||||||
@ -364,16 +368,16 @@ void MemorySanitizer::initializeCallbacks(Module &M) {
|
|||||||
"__msan_retval_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel);
|
"__msan_retval_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel);
|
||||||
|
|
||||||
ParamTLS = new GlobalVariable(
|
ParamTLS = new GlobalVariable(
|
||||||
M, ArrayType::get(IRB.getInt64Ty(), 1000), false,
|
M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false,
|
||||||
GlobalVariable::ExternalLinkage, nullptr, "__msan_param_tls", nullptr,
|
GlobalVariable::ExternalLinkage, nullptr, "__msan_param_tls", nullptr,
|
||||||
GlobalVariable::InitialExecTLSModel);
|
GlobalVariable::InitialExecTLSModel);
|
||||||
ParamOriginTLS = new GlobalVariable(
|
ParamOriginTLS = new GlobalVariable(
|
||||||
M, ArrayType::get(OriginTy, 1000), false, GlobalVariable::ExternalLinkage,
|
M, ArrayType::get(OriginTy, kParamTLSSize / 4), false,
|
||||||
nullptr, "__msan_param_origin_tls", nullptr,
|
GlobalVariable::ExternalLinkage, nullptr, "__msan_param_origin_tls",
|
||||||
GlobalVariable::InitialExecTLSModel);
|
nullptr, GlobalVariable::InitialExecTLSModel);
|
||||||
|
|
||||||
VAArgTLS = new GlobalVariable(
|
VAArgTLS = new GlobalVariable(
|
||||||
M, ArrayType::get(IRB.getInt64Ty(), 1000), false,
|
M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false,
|
||||||
GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr,
|
GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr,
|
||||||
GlobalVariable::InitialExecTLSModel);
|
GlobalVariable::InitialExecTLSModel);
|
||||||
VAArgOverflowSizeTLS = new GlobalVariable(
|
VAArgOverflowSizeTLS = new GlobalVariable(
|
||||||
@ -952,6 +956,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
? MS.DL->getTypeAllocSize(FArg.getType()->getPointerElementType())
|
? MS.DL->getTypeAllocSize(FArg.getType()->getPointerElementType())
|
||||||
: MS.DL->getTypeAllocSize(FArg.getType());
|
: MS.DL->getTypeAllocSize(FArg.getType());
|
||||||
if (A == &FArg) {
|
if (A == &FArg) {
|
||||||
|
bool Overflow = ArgOffset + Size > kParamTLSSize;
|
||||||
Value *Base = getShadowPtrForArgument(&FArg, EntryIRB, ArgOffset);
|
Value *Base = getShadowPtrForArgument(&FArg, EntryIRB, ArgOffset);
|
||||||
if (FArg.hasByValAttr()) {
|
if (FArg.hasByValAttr()) {
|
||||||
// ByVal pointer itself has clean shadow. We copy the actual
|
// ByVal pointer itself has clean shadow. We copy the actual
|
||||||
@ -962,19 +967,32 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
Type *EltType = A->getType()->getPointerElementType();
|
Type *EltType = A->getType()->getPointerElementType();
|
||||||
ArgAlign = MS.DL->getABITypeAlignment(EltType);
|
ArgAlign = MS.DL->getABITypeAlignment(EltType);
|
||||||
}
|
}
|
||||||
|
if (Overflow) {
|
||||||
|
// ParamTLS overflow.
|
||||||
|
EntryIRB.CreateMemSet(
|
||||||
|
getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB),
|
||||||
|
Constant::getNullValue(EntryIRB.getInt8Ty()), Size, ArgAlign);
|
||||||
|
} else {
|
||||||
unsigned CopyAlign = std::min(ArgAlign, kShadowTLSAlignment);
|
unsigned CopyAlign = std::min(ArgAlign, kShadowTLSAlignment);
|
||||||
Value *Cpy = EntryIRB.CreateMemCpy(
|
Value *Cpy = EntryIRB.CreateMemCpy(
|
||||||
getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), Base, Size,
|
getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), Base, Size,
|
||||||
CopyAlign);
|
CopyAlign);
|
||||||
DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n");
|
DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n");
|
||||||
(void)Cpy;
|
(void)Cpy;
|
||||||
|
}
|
||||||
*ShadowPtr = getCleanShadow(V);
|
*ShadowPtr = getCleanShadow(V);
|
||||||
} else {
|
} else {
|
||||||
*ShadowPtr = EntryIRB.CreateAlignedLoad(Base, kShadowTLSAlignment);
|
if (Overflow) {
|
||||||
|
// ParamTLS overflow.
|
||||||
|
*ShadowPtr = getCleanShadow(V);
|
||||||
|
} else {
|
||||||
|
*ShadowPtr =
|
||||||
|
EntryIRB.CreateAlignedLoad(Base, kShadowTLSAlignment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DEBUG(dbgs() << " ARG: " << FArg << " ==> " <<
|
DEBUG(dbgs() << " ARG: " << FArg << " ==> " <<
|
||||||
**ShadowPtr << "\n");
|
**ShadowPtr << "\n");
|
||||||
if (MS.TrackOrigins) {
|
if (MS.TrackOrigins && !Overflow) {
|
||||||
Value *OriginPtr =
|
Value *OriginPtr =
|
||||||
getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset);
|
getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset);
|
||||||
setOrigin(A, EntryIRB.CreateLoad(OriginPtr));
|
setOrigin(A, EntryIRB.CreateLoad(OriginPtr));
|
||||||
@ -2329,6 +2347,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
assert(A->getType()->isPointerTy() &&
|
assert(A->getType()->isPointerTy() &&
|
||||||
"ByVal argument is not a pointer!");
|
"ByVal argument is not a pointer!");
|
||||||
Size = MS.DL->getTypeAllocSize(A->getType()->getPointerElementType());
|
Size = MS.DL->getTypeAllocSize(A->getType()->getPointerElementType());
|
||||||
|
if (ArgOffset + Size > kParamTLSSize) break;
|
||||||
unsigned ParamAlignment = CS.getParamAlignment(i + 1);
|
unsigned ParamAlignment = CS.getParamAlignment(i + 1);
|
||||||
unsigned Alignment = std::min(ParamAlignment, kShadowTLSAlignment);
|
unsigned Alignment = std::min(ParamAlignment, kShadowTLSAlignment);
|
||||||
Store = IRB.CreateMemCpy(ArgShadowBase,
|
Store = IRB.CreateMemCpy(ArgShadowBase,
|
||||||
@ -2336,6 +2355,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
Size, Alignment);
|
Size, Alignment);
|
||||||
} else {
|
} else {
|
||||||
Size = MS.DL->getTypeAllocSize(A->getType());
|
Size = MS.DL->getTypeAllocSize(A->getType());
|
||||||
|
if (ArgOffset + Size > kParamTLSSize) break;
|
||||||
Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase,
|
Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase,
|
||||||
kShadowTLSAlignment);
|
kShadowTLSAlignment);
|
||||||
Constant *Cst = dyn_cast<Constant>(ArgShadow);
|
Constant *Cst = dyn_cast<Constant>(ArgShadow);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user