Skip to content

Commit e3cc8f3

Browse files
committed
[asan] Fix shadow load alignment for unaligned 128-bit load/store
When a 128-bit load/store is aligned by 8, we incorrectly emit `load i16, ptr ..., align 2` while the shadow memory address may not be aligned by 2. This manifests as possibly-misaligned shadow memory load with `-mstrict-align`, e.g. `clang --target=aarch64-linux -O2 -mstrict-align -fsanitize=address` ``` __attribute__((noinline)) void foo(unsigned long *ptr) { ptr[0] = 3; ptr[1] = 3; } // ldrh w8, [x9, x8] // the shadow memory load may not be aligned by 2 ``` Infer the shadow memory alignment from the load/store alignment to set the correct alignment. The generated code now uses two ldrb and one orr. Fix llvm#63258 Differential Revision: https://reviews.llvm.org/D152663
1 parent 3eb6fef commit e3cc8f3

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,8 @@ struct AddressSanitizer {
684684
const DataLayout &DL);
685685
void instrumentPointerComparisonOrSubtraction(Instruction *I);
686686
void instrumentAddress(Instruction *OrigIns, Instruction *InsertBefore,
687-
Value *Addr, uint32_t TypeStoreSize, bool IsWrite,
687+
Value *Addr, MaybeAlign Alignment,
688+
uint32_t TypeStoreSize, bool IsWrite,
688689
Value *SizeArgument, bool UseCalls, uint32_t Exp);
689690
Instruction *instrumentAMDGPUAddress(Instruction *OrigIns,
690691
Instruction *InsertBefore, Value *Addr,
@@ -1480,8 +1481,9 @@ static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I,
14801481
case 128:
14811482
if (!Alignment || *Alignment >= Granularity ||
14821483
*Alignment >= FixedSize / 8)
1483-
return Pass->instrumentAddress(I, InsertBefore, Addr, FixedSize,
1484-
IsWrite, nullptr, UseCalls, Exp);
1484+
return Pass->instrumentAddress(I, InsertBefore, Addr, Alignment,
1485+
FixedSize, IsWrite, nullptr, UseCalls,
1486+
Exp);
14851487
}
14861488
}
14871489
Pass->instrumentUnusualSizeOrAlignment(I, InsertBefore, Addr, TypeStoreSize,
@@ -1681,6 +1683,7 @@ Instruction *AddressSanitizer::instrumentAMDGPUAddress(
16811683

16821684
void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
16831685
Instruction *InsertBefore, Value *Addr,
1686+
MaybeAlign Alignment,
16841687
uint32_t TypeStoreSize, bool IsWrite,
16851688
Value *SizeArgument, bool UseCalls,
16861689
uint32_t Exp) {
@@ -1720,8 +1723,10 @@ void AddressSanitizer::instrumentAddress(Instruction *OrigIns,
17201723
IntegerType::get(*C, std::max(8U, TypeStoreSize >> Mapping.Scale));
17211724
Type *ShadowPtrTy = PointerType::get(ShadowTy, 0);
17221725
Value *ShadowPtr = memToShadow(AddrLong, IRB);
1723-
Value *ShadowValue =
1724-
IRB.CreateLoad(ShadowTy, IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy));
1726+
const uint64_t ShadowAlign =
1727+
std::max<uint64_t>(Alignment.valueOrOne().value() >> Mapping.Scale, 1);
1728+
Value *ShadowValue = IRB.CreateAlignedLoad(
1729+
ShadowTy, IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy), Align(ShadowAlign));
17251730

17261731
Value *Cmp = IRB.CreateIsNotNull(ShadowValue);
17271732
size_t Granularity = 1ULL << Mapping.Scale;
@@ -1778,8 +1783,9 @@ void AddressSanitizer::instrumentUnusualSizeOrAlignment(
17781783
Value *LastByte = IRB.CreateIntToPtr(
17791784
IRB.CreateAdd(AddrLong, SizeMinusOne),
17801785
Addr->getType());
1781-
instrumentAddress(I, InsertBefore, Addr, 8, IsWrite, Size, false, Exp);
1782-
instrumentAddress(I, InsertBefore, LastByte, 8, IsWrite, Size, false, Exp);
1786+
instrumentAddress(I, InsertBefore, Addr, {}, 8, IsWrite, Size, false, Exp);
1787+
instrumentAddress(I, InsertBefore, LastByte, {}, 8, IsWrite, Size, false,
1788+
Exp);
17831789
}
17841790
}
17851791

llvm/test/Instrumentation/AddressSanitizer/basic.ll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,27 @@ define void @i64test_align1(ptr %b) nounwind uwtable sanitize_address {
135135
; CHECK: __asan_report_store_n{{.*}}, i64 8)
136136
; CHECK: ret void
137137

138+
define void @i128test_align8(ptr %a) nounwind uwtable sanitize_address {
139+
entry:
140+
store i128 0, ptr %a, align 8
141+
ret void
142+
}
143+
; CHECK-LABEL: define {{[^@]+}}@i128test_align8(
144+
; CHECK-S3: load i16, ptr %[[#]], align 1
145+
; CHECK-S3-NEXT: icmp ne i16 %[[#]], 0
146+
; CHECK-S5: load i8, ptr %[[#]], align 1
147+
; CHECK-S5: load i8, ptr %[[#]], align 1
148+
149+
define void @i128test_align16(ptr %a) nounwind uwtable sanitize_address {
150+
entry:
151+
store i128 0, ptr %a, align 16
152+
ret void
153+
}
154+
; CHECK-LABEL: define {{[^@]+}}@i128test_align16(
155+
; CHECK-S3: load i16, ptr %[[#]], align 2
156+
; CHECK-S3-NEXT: icmp ne i16 %[[#]], 0
157+
; CHECK-S5: load i8, ptr %[[#]], align 1
158+
; CHECK-S5-NEXT: icmp ne i8 %[[#]], 0
138159

139160
define void @i80test(ptr %a, ptr %b) nounwind uwtable sanitize_address {
140161
entry:

llvm/test/Instrumentation/AddressSanitizer/vector-load-store.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,31 @@ define void @store.v16i32(ptr %p) sanitize_address {
375375
ret void
376376
}
377377

378+
define void @store.v2i32.align8(ptr %p) sanitize_address {
379+
; CHECK-LABEL: @store.v2i32.align8(
380+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
381+
; CHECK-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 3
382+
; CHECK-NEXT: [[TMP3:%.*]] = or i64 [[TMP2]], 17592186044416
383+
; CHECK-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
384+
; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1
385+
; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i8 [[TMP5]], 0
386+
; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP8:%.*]]
387+
; CHECK: 7:
388+
; CHECK-NEXT: call void @__asan_report_store8(i64 [[TMP1]]) #[[ATTR4]]
389+
; CHECK-NEXT: unreachable
390+
; CHECK: 8:
391+
; CHECK-NEXT: store <2 x i32> zeroinitializer, ptr [[P]], align 8
392+
; CHECK-NEXT: ret void
393+
;
394+
; CALLS-LABEL: @store.v2i32.align8(
395+
; CALLS-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
396+
; CALLS-NEXT: call void @__asan_store8(i64 [[TMP1]])
397+
; CALLS-NEXT: store <2 x i32> zeroinitializer, ptr [[P]], align 8
398+
; CALLS-NEXT: ret void
399+
;
400+
store <2 x i32> zeroinitializer, ptr %p, align 8
401+
ret void
402+
}
378403

379404
define void @load.nxv1i32(ptr %p) sanitize_address {
380405
; CHECK-LABEL: @load.nxv1i32(

0 commit comments

Comments
 (0)