Skip to content

Commit 844c731

Browse files
authored
[HWASAN] Mark built-ins as not built-ins to prevent optimizations (llvm#68936)
The other 3 sanitizers (ASAN, TSAN and MSAN) all use maybeMarkSanitizerLibraryCallNoBuiltin to make disable optimizations which inline functions like memcmp for example. The lack of this optimization was allowing ExpandMemCmpPass to convert a memcmp call to inlined assembly and cause a false negative in HWASAN.
1 parent b49a0db commit 844c731

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

compiler-rt/test/hwasan/TestCases/memcmp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
int main(int argc, char **argv) {
1212
__hwasan_enable_allocator_tagging();
1313
char a[] = {static_cast<char>(argc), 2, 3, 4};
14-
volatile int size = sizeof(a);
15-
char *volatile p = (char *)malloc(size);
14+
int size = sizeof(a);
15+
char *p = (char *)malloc(size);
1616
memcpy(p, a, size);
1717
free(p);
1818
return memcmp(p, a, size);

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/Analysis/GlobalsModRef.h"
2222
#include "llvm/Analysis/PostDominators.h"
2323
#include "llvm/Analysis/StackSafetyAnalysis.h"
24+
#include "llvm/Analysis/TargetLibraryInfo.h"
2425
#include "llvm/Analysis/ValueTracking.h"
2526
#include "llvm/BinaryFormat/Dwarf.h"
2627
#include "llvm/BinaryFormat/ELF.h"
@@ -52,6 +53,7 @@
5253
#include "llvm/TargetParser/Triple.h"
5354
#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
5455
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
56+
#include "llvm/Transforms/Utils/Local.h"
5557
#include "llvm/Transforms/Utils/MemoryTaggingSupport.h"
5658
#include "llvm/Transforms/Utils/ModuleUtils.h"
5759
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
@@ -320,7 +322,8 @@ class HWAddressSanitizer {
320322
LoopInfo *LI);
321323
bool ignoreAccess(Instruction *Inst, Value *Ptr);
322324
void getInterestingMemoryOperands(
323-
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting);
325+
Instruction *I, const TargetLibraryInfo &TLI,
326+
SmallVectorImpl<InterestingMemoryOperand> &Interesting);
324327

325328
void tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag, size_t Size);
326329
Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
@@ -779,7 +782,8 @@ bool HWAddressSanitizer::ignoreAccess(Instruction *Inst, Value *Ptr) {
779782
}
780783

781784
void HWAddressSanitizer::getInterestingMemoryOperands(
782-
Instruction *I, SmallVectorImpl<InterestingMemoryOperand> &Interesting) {
785+
Instruction *I, const TargetLibraryInfo &TLI,
786+
SmallVectorImpl<InterestingMemoryOperand> &Interesting) {
783787
// Skip memory accesses inserted by another instrumentation.
784788
if (I->hasMetadata(LLVMContext::MD_nosanitize))
785789
return;
@@ -817,6 +821,7 @@ void HWAddressSanitizer::getInterestingMemoryOperands(
817821
Type *Ty = CI->getParamByValType(ArgNo);
818822
Interesting.emplace_back(I, ArgNo, false, Ty, Align(1));
819823
}
824+
maybeMarkSanitizerLibraryCallNoBuiltin(CI, &TLI);
820825
}
821826
}
822827

@@ -1493,6 +1498,7 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
14931498
SmallVector<InterestingMemoryOperand, 16> OperandsToInstrument;
14941499
SmallVector<MemIntrinsic *, 16> IntrinToInstrument;
14951500
SmallVector<Instruction *, 8> LandingPadVec;
1501+
const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
14961502

14971503
memtag::StackInfoBuilder SIB(SSI);
14981504
for (auto &Inst : instructions(F)) {
@@ -1503,7 +1509,7 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
15031509
if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
15041510
LandingPadVec.push_back(&Inst);
15051511

1506-
getInterestingMemoryOperands(&Inst, OperandsToInstrument);
1512+
getInterestingMemoryOperands(&Inst, TLI, OperandsToInstrument);
15071513

15081514
if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&Inst))
15091515
if (!ignoreMemIntrinsic(MI))
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; Test marking string functions as nobuiltin in address sanitizer.
2+
;
3+
; RUN: opt < %s -passes=hwasan -S | FileCheck %s
4+
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"
5+
target triple = "x86_64-unknown-linux-gnu"
6+
7+
declare ptr @memchr(ptr %a, i32 %b, i64 %c)
8+
declare i32 @memcmp(ptr %a, ptr %b, i64 %c)
9+
declare i32 @strcmp(ptr %a, ptr %b)
10+
declare ptr @strcpy(ptr %a, ptr %b)
11+
declare ptr @stpcpy(ptr %a, ptr %b)
12+
declare i64 @strlen(ptr %a)
13+
declare i64 @strnlen(ptr %a, i64 %b)
14+
15+
; CHECK: call{{.*}}@memchr{{.*}} #[[ATTR:[0-9]+]]
16+
; CHECK: call{{.*}}@memcmp{{.*}} #[[ATTR]]
17+
; CHECK: call{{.*}}@strcmp{{.*}} #[[ATTR]]
18+
; CHECK: call{{.*}}@strcpy{{.*}} #[[ATTR]]
19+
; CHECK: call{{.*}}@stpcpy{{.*}} #[[ATTR]]
20+
; CHECK: call{{.*}}@strlen{{.*}} #[[ATTR]]
21+
; CHECK: call{{.*}}@strnlen{{.*}} #[[ATTR]]
22+
; attributes #[[ATTR]] = { nobuiltin }
23+
24+
define void @f1(ptr %a, ptr %b) nounwind uwtable sanitize_hwaddress {
25+
tail call ptr @memchr(ptr %a, i32 1, i64 12)
26+
tail call i32 @memcmp(ptr %a, ptr %b, i64 12)
27+
tail call i32 @strcmp(ptr %a, ptr %b)
28+
tail call ptr @strcpy(ptr %a, ptr %b)
29+
tail call ptr @stpcpy(ptr %a, ptr %b)
30+
tail call i64 @strlen(ptr %a)
31+
tail call i64 @strnlen(ptr %a, i64 12)
32+
ret void
33+
}

0 commit comments

Comments
 (0)