Skip to content

Commit e4db3f0

Browse files
[llvm] Bail out when meeting pointer with negative offset in approximated mode instead of … (#120424)
…generating empty location Fix the regression detected by llvm/llvm-test-suite#188
1 parent 000febd commit e4db3f0

File tree

4 files changed

+32
-7
lines changed

4 files changed

+32
-7
lines changed

llvm/lib/Analysis/MemoryBuiltins.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -838,11 +838,14 @@ OffsetSpan ObjectSizeOffsetVisitor::computeImpl(Value *V) {
838838

839839
// We end up pointing on a location that's outside of the original object.
840840
if (ORT.knownBefore() && ORT.Before.isNegative()) {
841-
// This is UB, and we'd rather return an empty location then.
841+
// This means that we *may* be accessing memory before the allocation.
842+
// Conservatively return an unknown size.
843+
//
844+
// TODO: working with ranges instead of value would make it possible to take
845+
// a better decision.
842846
if (Options.EvalMode == ObjectSizeOpts::Mode::Min ||
843847
Options.EvalMode == ObjectSizeOpts::Mode::Max) {
844-
ORT.Before = APInt::getZero(ORT.Before.getBitWidth());
845-
ORT.After = APInt::getZero(ORT.Before.getBitWidth());
848+
return ObjectSizeOffsetVisitor::unknown();
846849
}
847850
// Otherwise it's fine, caller can handle negative offset.
848851
}

llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ define dso_local i64 @pick_max_one_oob(i1 %c0, i1 %c1) {
143143
; CHECK-NEXT: br label [[IF_END]]
144144
; CHECK: if.end:
145145
; CHECK-NEXT: [[P_END:%.*]] = phi ptr [ [[P_ELSE]], [[IF_ELSE]] ], [ [[P_THEN]], [[IF_THEN]] ]
146-
; CHECK-NEXT: [[OBJSIZE:%.*]] = select i1 [[C1:%.*]], i64 1, i64 0
146+
; CHECK-NEXT: [[OBJSIZE:%.*]] = select i1 [[C1:%.*]], i64 -1, i64 0
147147
; CHECK-NEXT: ret i64 [[OBJSIZE]]
148148
;
149149
%p = alloca [2 x i8], align 1

llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-range.ll

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ define i64 @select_neg_oob_offset(i1 %c0, i1 %c1) {
7878
; CHECK-NEXT: [[PTR:%.*]] = alloca i8, i64 10, align 1
7979
; CHECK-NEXT: [[OFFSET:%.*]] = select i1 [[C0:%.*]], i64 -3, i64 -4
8080
; CHECK-NEXT: [[PTR_SLIDE:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 [[OFFSET]]
81-
; CHECK-NEXT: ret i64 0
81+
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1:%.*]], i64 -1, i64 0
82+
; CHECK-NEXT: ret i64 [[RES]]
8283
;
8384
%ptr = alloca i8, i64 10
8485
%offset = select i1 %c0, i64 -3, i64 -4
@@ -106,4 +107,25 @@ define i64 @select_gep_offsets(i1 %cond) {
106107
ret i64 %res
107108
}
108109

110+
define i64 @select_gep_oob_overapproximated_offsets(i1 %cond) {
111+
; CHECK-LABEL: @select_gep_oob_overapproximated_offsets(
112+
; CHECK-NEXT: [[BASE1:%.*]] = alloca [288 x i8], align 16
113+
; CHECK-NEXT: [[SELECT0:%.*]] = select i1 [[COND:%.*]], i64 -4, i64 -64
114+
; CHECK-NEXT: [[SELECT1:%.*]] = select i1 [[COND]], i64 16, i64 64
115+
; CHECK-NEXT: [[GEP0:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE1]], i64 [[SELECT1]]
116+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[GEP0]], i64 [[SELECT0]]
117+
; CHECK-NEXT: ret i64 -1
118+
;
119+
%base1 = alloca [288 x i8], align 16
120+
%select0 = select i1 %cond, i64 -4, i64 -64
121+
%select1 = select i1 %cond, i64 16, i64 64
122+
; This never actually goes oob, but because we approximate each select
123+
; independently, this actually ranges in [16 - 64 ; 64 - 4] instead of [64 - 64; 16 - 4]
124+
%gep0 = getelementptr inbounds nuw i8, ptr %base1, i64 %select1
125+
%gep1 = getelementptr inbounds i8, ptr %gep0, i64 %select0
126+
%call = call i64 @llvm.objectsize.i64.p0(ptr %gep1, i1 false, i1 true, i1 false)
127+
ret i64 %call
128+
}
129+
130+
109131
attributes #0 = { nounwind allocsize(0) }

llvm/test/Transforms/LowerConstantIntrinsics/objectsize_basic.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ define i64 @wrapping_gep_neg(i1 %c) {
214214
; CHECK-NEXT: [[OBJ:%.*]] = alloca i8, i64 4, align 1
215215
; CHECK-NEXT: [[SLIDE:%.*]] = getelementptr i8, ptr [[OBJ]], i64 9223372036854775807
216216
; CHECK-NEXT: [[SLIDE_BIS:%.*]] = getelementptr i8, ptr [[SLIDE]], i64 9223372036854775807
217-
; CHECK-NEXT: ret i64 0
217+
; CHECK-NEXT: ret i64 -1
218218
;
219219
%obj = alloca i8, i64 4
220220
%slide = getelementptr i8, ptr %obj, i64 9223372036854775807
@@ -269,7 +269,7 @@ define i64 @out_of_bound_negative_gep(i1 %c) {
269269
; CHECK-LABEL: @out_of_bound_negative_gep(
270270
; CHECK-NEXT: [[OBJ:%.*]] = alloca i8, i32 4, align 1
271271
; CHECK-NEXT: [[SLIDE:%.*]] = getelementptr i8, ptr [[OBJ]], i8 -8
272-
; CHECK-NEXT: ret i64 0
272+
; CHECK-NEXT: ret i64 -1
273273
;
274274
%obj = alloca i8, i32 4
275275
%slide = getelementptr i8, ptr %obj, i8 -8

0 commit comments

Comments
 (0)