[llvm] [llvm::transforms] Add overflow check in AllocaInst::getAllocationSize (PR #97170)
Tsz Chan via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 29 12:22:46 PDT 2024
https://github.com/tszhin-swe updated https://github.com/llvm/llvm-project/pull/97170
>From 86c9af9ca63cbab1e81d417d6c85ab131aef0ccf Mon Sep 17 00:00:00 2001
From: Tsz Chan <keithcth2001 at gmail.com>
Date: Sun, 30 Jun 2024 01:39:51 +0800
Subject: [PATCH] [llvm::transforms] Add overflow check in
AllocaInst::getAllocationSize
---
llvm/lib/IR/Instructions.cpp | 30 ++++++++++++++++----------
llvm/unittests/IR/InstructionsTest.cpp | 3 +++
2 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 494306815d90d..cd2f95cd2967f 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -37,6 +37,7 @@
#include "llvm/IR/Value.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CheckedArithmetic.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ModRef.h"
@@ -60,22 +61,29 @@ static cl::opt<bool> DisableI2pP2iOpt(
std::optional<TypeSize>
AllocaInst::getAllocationSize(const DataLayout &DL) const {
TypeSize Size = DL.getTypeAllocSize(getAllocatedType());
- if (isArrayAllocation()) {
- auto *C = dyn_cast<ConstantInt>(getArraySize());
- if (!C)
- return std::nullopt;
- assert(!Size.isScalable() && "Array elements cannot have a scalable size");
- Size *= C->getZExtValue();
- }
- return Size;
+ if (!isArrayAllocation())
+ return Size;
+ auto *C = dyn_cast<ConstantInt>(getArraySize());
+ if (!C)
+ return std::nullopt;
+ assert(!Size.isScalable() && "Array elements cannot have a scalable size");
+ auto checkedProd =
+ checkedMulUnsigned(Size.getKnownMinValue(), C->getZExtValue());
+ if (!checkedProd)
+ return std::nullopt;
+ return TypeSize::getFixed(*checkedProd);
}
std::optional<TypeSize>
AllocaInst::getAllocationSizeInBits(const DataLayout &DL) const {
std::optional<TypeSize> Size = getAllocationSize(DL);
- if (Size)
- return *Size * 8;
- return std::nullopt;
+ if (!Size)
+ return std::nullopt;
+ auto CheckedProd = checkedMulUnsigned((*Size).getKnownMinValue(),
+ static_cast<TypeSize::ScalarTy>(8));
+ if (!CheckedProd)
+ return std::nullopt;
+ return TypeSize::get(*CheckedProd, (*Size).isScalable());
}
//===----------------------------------------------------------------------===//
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index b6044b2862920..4c1e9a9acb29a 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -1750,6 +1750,7 @@ TEST(InstructionsTest, AllocaInst) {
%F = alloca [2 x half]
%G = alloca [2 x [3 x i128]]
%H = alloca %T
+ %I = alloca i32, i64 9223372036854775807
ret void
}
)");
@@ -1766,6 +1767,7 @@ TEST(InstructionsTest, AllocaInst) {
AllocaInst &F = cast<AllocaInst>(*It++);
AllocaInst &G = cast<AllocaInst>(*It++);
AllocaInst &H = cast<AllocaInst>(*It++);
+ AllocaInst &I = cast<AllocaInst>(*It++);
EXPECT_EQ(A.getAllocationSizeInBits(DL), TypeSize::getFixed(32));
EXPECT_EQ(B.getAllocationSizeInBits(DL), TypeSize::getFixed(128));
EXPECT_FALSE(C.getAllocationSizeInBits(DL));
@@ -1774,6 +1776,7 @@ TEST(InstructionsTest, AllocaInst) {
EXPECT_EQ(F.getAllocationSizeInBits(DL), TypeSize::getFixed(32));
EXPECT_EQ(G.getAllocationSizeInBits(DL), TypeSize::getFixed(768));
EXPECT_EQ(H.getAllocationSizeInBits(DL), TypeSize::getFixed(160));
+ EXPECT_FALSE(I.getAllocationSizeInBits(DL));
}
TEST(InstructionsTest, InsertAtBegin) {
More information about the llvm-commits
mailing list