[llvm] [WIP] [llvm::transforms] Add overflow check in AllocaInst::getAllocationSize (PR #96668)

Tsz Chan via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 25 10:58:44 PDT 2024


https://github.com/tszhin-swe updated https://github.com/llvm/llvm-project/pull/96668

>From cadadb9a8780c7b63785c480e70100f9968e1292 Mon Sep 17 00:00:00 2001
From: Tsz Chan <keithcth2001 at gmail.com>
Date: Tue, 25 Jun 2024 16:56:28 +0000
Subject: [PATCH] [llvm::transforms] Add overflow check in
 AllocaInst::getAllocationSize

---
 llvm/lib/IR/Instructions.cpp           | 35 ++++++++++++++++++--------
 llvm/unittests/IR/InstructionsTest.cpp |  3 +++
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 2e1fd2a96ffff..f3b0468ec9d94 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -41,6 +41,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/ModRef.h"
 #include "llvm/Support/TypeSize.h"
+#include "llvm/Support/CheckedArithmetic.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -60,22 +61,34 @@ 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();
+  if (!isArrayAllocation()) {
+    return Size;
   }
-  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(static_cast<TypeSize::ScalarTy>(Size),
+                                        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;
+  std::optional<TypeSize> OptSize = getAllocationSize(DL);
+  if (!OptSize) {
+    return std::nullopt;
+  }
+  auto CheckedProd =
+      checkedMulUnsigned(static_cast<TypeSize::ScalarTy>(*OptSize),
+                         static_cast<TypeSize::ScalarTy>(8));
+  if (!CheckedProd) {
+    return std::nullopt;
+  }
+  return TypeSize::getFixed(*CheckedProd);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index b6044b2862920..7699fd3ee6681 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, i32 1000000000 ; Allocation causing overflow
         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_EQ(I.getAllocationSizeInBits(DL), TypeSize::getFixed(160));
 }
 
 TEST(InstructionsTest, InsertAtBegin) {



More information about the llvm-commits mailing list