Index: lib/CodeGen/SafeStack.cpp =================================================================== --- lib/CodeGen/SafeStack.cpp +++ lib/CodeGen/SafeStack.cpp @@ -260,8 +260,14 @@ bool SafeStack::IsMemIntrinsicSafe(const MemIntrinsic *MI, const Use &U, const Value *AllocaPtr, uint64_t AllocaSize) { - // All MemIntrinsics have destination address in Arg0 and size in Arg2. - if (MI->getRawDest() != U) return true; + if (auto MTI = dyn_cast(MI)) { + if (MTI->getRawSource() != U && MTI->getRawDest() != U) + return true; + } else { + if (MI->getRawDest() != U) + return true; + } + const auto *Len = dyn_cast(MI->getLength()); // Non-constant size => unsafe. FIXME: try SCEV getRange. if (!Len) return false; Index: test/Transforms/SafeStack/X86/memintrinsic-oob-read.ll =================================================================== --- /dev/null +++ test/Transforms/SafeStack/X86/memintrinsic-oob-read.ll @@ -0,0 +1,14 @@ +; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s +; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i1) + +; CHECK: __safestack_unsafe_stack_ptr +define void @oob_read(i8* %ptr) safestack { + %1 = alloca i8 + call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %ptr, i8* align 1 %1, i64 4, i1 false) + ret void +}