Skip to content

Commit bb34b1d

Browse files
committed
[msan] Improve instrumentation of disjoint OR
The disjoint OR (#72583) of two '1's is poison, hence the corresponding shadow memory needs to be uninitialized (rather than initialized, as per the existing instrumentation which ignores disjointedness). Updates the test from #145982
1 parent 9e4981c commit bb34b1d

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,11 +2497,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
24972497

24982498
void visitOr(BinaryOperator &I) {
24992499
IRBuilder<> IRB(&I);
2500-
// "Or" of 1 and a poisoned value results in unpoisoned value.
2501-
// 1|1 => 1; 0|1 => 1; p|1 => 1;
2502-
// 1|0 => 1; 0|0 => 0; p|0 => p;
2503-
// 1|p => 1; 0|p => p; p|p => p;
2504-
// S = (S1 & S2) | (~V1 & S2) | (S1 & ~V2)
2500+
// "Or" of 1 and a poisoned value results in unpoisoned value:
2501+
// 1|1 => 1; 0|1 => 1; p|1 => 1;
2502+
// 1|0 => 1; 0|0 => 0; p|0 => p;
2503+
// 1|p => 1; 0|p => p; p|p => p;
2504+
//
2505+
// S = (S1 & S2) | (~V1 & S2) | (S1 & ~V2)
2506+
//
2507+
// Addendum if the "Or" is "disjoint":
2508+
// 1|1 => p;
2509+
// S = S | (V1 & V2)
25052510
Value *S1 = getShadow(&I, 0);
25062511
Value *S2 = getShadow(&I, 1);
25072512
Value *V1 = IRB.CreateNot(I.getOperand(0));
@@ -2513,7 +2518,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
25132518
Value *S1S2 = IRB.CreateAnd(S1, S2);
25142519
Value *V1S2 = IRB.CreateAnd(V1, S2);
25152520
Value *S1V2 = IRB.CreateAnd(S1, V2);
2516-
setShadow(&I, IRB.CreateOr({S1S2, V1S2, S1V2}));
2521+
2522+
Value *S = IRB.CreateOr({S1S2, V1S2, S1V2});
2523+
auto* MaybeDisjoint = cast<PossiblyDisjointInst>(&I);
2524+
if (MaybeDisjoint->isDisjoint()) {
2525+
Value *V1V2 = IRB.CreateAnd(V1, V2);
2526+
S = IRB.CreateOr({S, V1V2});
2527+
}
2528+
2529+
setShadow(&I, S);
25172530
setOriginForNaryOp(I);
25182531
}
25192532

llvm/test/Instrumentation/MemorySanitizer/or.ll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ define i8 @test_disjoint_or(i8 %a, i8 %b) sanitize_memory {
4141
; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[TMP1]], [[TMP4]]
4242
; CHECK-NEXT: [[TMP8:%.*]] = or i8 [[TMP5]], [[TMP6]]
4343
; CHECK-NEXT: [[TMP11:%.*]] = or i8 [[TMP8]], [[TMP7]]
44+
; CHECK-NEXT: [[TMP10:%.*]] = and i8 [[TMP3]], [[TMP4]]
45+
; CHECK-NEXT: [[TMP12:%.*]] = or i8 [[TMP11]], [[TMP10]]
4446
; CHECK-NEXT: [[C:%.*]] = or disjoint i8 [[A]], [[B]]
45-
; CHECK-NEXT: store i8 [[TMP11]], ptr @__msan_retval_tls, align 8
47+
; CHECK-NEXT: store i8 [[TMP12]], ptr @__msan_retval_tls, align 8
4648
; CHECK-NEXT: ret i8 [[C]]
4749
;
4850
%c = or disjoint i8 %a, %b

0 commit comments

Comments
 (0)