Skip to content

Commit b11b60d

Browse files
committed
[InterleavedAccessAnalysis] Fix integer overflow in insertMember.
Without checking for integer overflow, invalid members can be added e.g. if the calculated key overflows, becomes positive and the largest key. This fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7560 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13128 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13229 Reviewers: Ayal, anna, hsaito, efriedma Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D55538 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355613 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 527cd07 commit b11b60d

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

include/llvm/Analysis/VectorUtils.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/Analysis/LoopAccessAnalysis.h"
1818
#include "llvm/Analysis/TargetLibraryInfo.h"
1919
#include "llvm/IR/IRBuilder.h"
20+
#include "llvm/Support/CheckedArithmetic.h"
2021

2122
namespace llvm {
2223

@@ -277,21 +278,31 @@ template <typename InstTy> class InterleaveGroup {
277278
bool insertMember(InstTy *Instr, int32_t Index, uint32_t NewAlign) {
278279
assert(NewAlign && "The new member's alignment should be non-zero");
279280

280-
int32_t Key = Index + SmallestKey;
281+
// Make sure the key fits in an int32_t.
282+
Optional<int32_t> MaybeKey = checkedAdd(Index, SmallestKey);
283+
if (!MaybeKey)
284+
return false;
285+
int32_t Key = *MaybeKey;
281286

282287
// Skip if there is already a member with the same index.
283288
if (Members.find(Key) != Members.end())
284289
return false;
285290

286291
if (Key > LargestKey) {
287292
// The largest index is always less than the interleave factor.
288-
if (Index >= static_cast<int>(Factor))
293+
if (Index >= static_cast<int32_t>(Factor))
289294
return false;
290295

291296
LargestKey = Key;
292297
} else if (Key < SmallestKey) {
298+
299+
// Make sure the largest index fits in an int32_t.
300+
Optional<int32_t> MaybeLargestIndex = checkedSub(LargestKey, Key);
301+
if (!MaybeLargestIndex)
302+
return false;
303+
293304
// The largest index is always less than the interleave factor.
294-
if (LargestKey - Key >= static_cast<int>(Factor))
305+
if (*MaybeLargestIndex >= static_cast<int64_t>(Factor))
295306
return false;
296307

297308
SmallestKey = Key;

include/llvm/Support/CheckedArithmetic.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ checkedAdd(T LHS, T RHS) {
4949
return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov);
5050
}
5151

52+
/// Subtract two signed integers \p LHS and \p RHS.
53+
/// \return Optional of sum if no signed overflow occurred,
54+
/// \c None otherwise.
55+
template <typename T>
56+
typename std::enable_if<std::is_signed<T>::value, llvm::Optional<T>>::type
57+
checkedSub(T LHS, T RHS) {
58+
return checkedOp(LHS, RHS, &llvm::APInt::ssub_ov);
59+
}
60+
5261
/// Multiply two signed integers \p LHS and \p RHS.
5362
/// \return Optional of product if no signed overflow occurred,
5463
/// \c None otherwise.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: opt < %s -loop-vectorize -mtriple x86_64 -S | FileCheck %s
2+
3+
%struct.ST4 = type { i32, i32, i32, i32 }
4+
5+
; The gaps between the memory access in this function are too large for
6+
; interleaving.
7+
8+
; Test from https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7560
9+
define void @test1(%struct.ST4* noalias %B) {
10+
; CHECK-LABEL: @test1
11+
; CHECK-NEXT: entry:
12+
; CHECK-NEXT: br label %for.body
13+
14+
; CHECK-LABEL: for.body:
15+
; CHECK: store i32
16+
; CHECK: store i32
17+
; CHECK: store i32
18+
; CHECK: store i32
19+
; CHECK-NOT: store
20+
;
21+
entry:
22+
br label %for.body
23+
24+
for.body: ; preds = %for.body, %entry
25+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
26+
%p1 = getelementptr inbounds %struct.ST4, %struct.ST4* %B, i64 %indvars.iv, i32 0
27+
store i32 65536, i32* %p1, align 4
28+
%p2 = getelementptr i32, i32* %p1, i32 -2147483648
29+
store i32 65536, i32* %p2, align 4
30+
%p3 = getelementptr inbounds %struct.ST4, %struct.ST4* %B, i64 %indvars.iv, i32 2
31+
store i32 10, i32* %p3, align 4
32+
%p4 = getelementptr inbounds %struct.ST4, %struct.ST4* %B, i64 %indvars.iv, i32 3
33+
store i32 12, i32* %p4, align 4
34+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
35+
%exitcond = icmp eq i64 %indvars.iv.next, 1024
36+
br i1 %exitcond, label %for.cond.cleanup, label %for.body
37+
38+
for.cond.cleanup: ; preds = %for.body
39+
ret void
40+
}

0 commit comments

Comments
 (0)