diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index f4f62a31d89ee7..427abde4277d4f 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1149,36 +1149,30 @@ struct MemorySanitizerVisitor : public InstVisitor { const DataLayout &DL = F.getParent()->getDataLayout(); const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment); unsigned StoreSize = DL.getTypeStoreSize(Shadow->getType()); - if (Shadow->getType()->isArrayTy()) { - paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize, - OriginAlignment); - } else { - Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB); - if (auto *ConstantShadow = dyn_cast(ConvertedShadow)) { - if (ClCheckConstantShadow && !ConstantShadow->isZeroValue()) - paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize, - OriginAlignment); - return; - } - - unsigned TypeSizeInBits = - DL.getTypeSizeInBits(ConvertedShadow->getType()); - unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits); - if (AsCall && SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) { - FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex]; - Value *ConvertedShadow2 = IRB.CreateZExt( - ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex))); - IRB.CreateCall(Fn, {ConvertedShadow2, - IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), - Origin}); - } else { - Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp"); - Instruction *CheckTerm = SplitBlockAndInsertIfThen( - Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights); - IRBuilder<> IRBNew(CheckTerm); - paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize, + Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB); + if (auto *ConstantShadow = dyn_cast(ConvertedShadow)) { + if (ClCheckConstantShadow && !ConstantShadow->isZeroValue()) + paintOrigin(IRB, updateOrigin(Origin, IRB), OriginPtr, StoreSize, OriginAlignment); - } + return; + } + + unsigned TypeSizeInBits = DL.getTypeSizeInBits(ConvertedShadow->getType()); + unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits); + if (AsCall && SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) { + FunctionCallee Fn = MS.MaybeStoreOriginFn[SizeIndex]; + Value *ConvertedShadow2 = + IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex))); + IRB.CreateCall(Fn, + {ConvertedShadow2, + IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()), Origin}); + } else { + Value *Cmp = convertToBool(ConvertedShadow, IRB, "_mscmp"); + Instruction *CheckTerm = SplitBlockAndInsertIfThen( + Cmp, &*IRB.GetInsertPoint(), false, MS.OriginStoreWeights); + IRBuilder<> IRBNew(CheckTerm); + paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), OriginPtr, StoreSize, + OriginAlignment); } } @@ -1410,12 +1404,31 @@ struct MemorySanitizerVisitor : public InstVisitor { return Aggregator; } + // Extract combined shadow of array elements + Value *collapseArrayShadow(ArrayType *Array, Value *Shadow, + IRBuilder<> &IRB) { + if (!Array->getNumElements()) + return IRB.getIntN(/* width */ 1, /* value */ 0); + + Value *FirstItem = IRB.CreateExtractValue(Shadow, 0); + Value *Aggregator = convertShadowToScalar(FirstItem, IRB); + + for (unsigned Idx = 1; Idx < Array->getNumElements(); Idx++) { + Value *ShadowItem = IRB.CreateExtractValue(Shadow, Idx); + Value *ShadowInner = convertShadowToScalar(ShadowItem, IRB); + Aggregator = IRB.CreateOr(Aggregator, ShadowInner); + } + return Aggregator; + } + /// Convert a shadow value to it's flattened variant. The resulting /// shadow may not necessarily have the same bit width as the input /// value, but it will always be comparable to zero. Value *convertShadowToScalar(Value *V, IRBuilder<> &IRB) { if (StructType *Struct = dyn_cast(V->getType())) return collapseStructShadow(Struct, V, IRB); + if (ArrayType *Array = dyn_cast(V->getType())) + return collapseArrayShadow(Array, V, IRB); Type *Ty = V->getType(); Type *NoVecTy = getShadowTyNoVec(Ty); if (Ty == NoVecTy) return V; @@ -1765,10 +1778,10 @@ struct MemorySanitizerVisitor : public InstVisitor { if (!InsertChecks) return; #ifndef NDEBUG Type *ShadowTy = Shadow->getType(); - assert( - (isa(ShadowTy) || isa(ShadowTy) || - isa(ShadowTy)) && - "Can only insert checks for integer, vector, and struct shadow types"); + assert((isa(ShadowTy) || isa(ShadowTy) || + isa(ShadowTy) || isa(ShadowTy)) && + "Can only insert checks for integer, vector, and aggregate shadow " + "types"); #endif InstrumentationList.push_back( ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns)); diff --git a/llvm/test/Instrumentation/MemorySanitizer/check-array.ll b/llvm/test/Instrumentation/MemorySanitizer/check-array.ll new file mode 100644 index 00000000000000..6d1e517a186d48 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/check-array.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -msan-eager-checks -msan-check-access-address=0 -msan-track-origins=1 -S -passes='module(msan-module),function(msan)' 2>&1 | \ +; RUN: FileCheck -allow-deprecated-dag-overlap -check-prefixes=CHECK,CHECK-ORIGINS %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define noundef [2 x i24] @check_array([2 x i24]* %p) sanitize_memory { +; CHECK: @check_array([2 x i24]* [[P:%.*]]) +; CHECK: [[O:%.*]] = load [2 x i24], [2 x i24]* [[P]] + %o = load [2 x i24], [2 x i24]* %p +; CHECK: [[FIELD0:%.+]] = extractvalue [2 x i24] %_msld, 0 +; CHECK: [[FIELD1:%.+]] = extractvalue [2 x i24] %_msld, 1 +; CHECK: [[F1_OR:%.+]] = or i24 [[FIELD0]], [[FIELD1]] +; CHECK: %_mscmp = icmp ne i24 [[F1_OR]], 0 +; CHECK: br i1 %_mscmp +; CHECK: call void @__msan_warning +; CHECK: ret [2 x i24] [[O]] + ret [2 x i24] %o +}