[PATCH] D43218: [analyzer] Quickfix: do not overflow in calculating offset in RegionManager
George Karpenkov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 26 13:05:27 PST 2018
This revision was automatically updated to reflect the committed changes.
Closed by commit rC326122: [analyzer] Quickfix: do not overflow in calculating offset in RegionManager (authored by george.karpenkov, committed by ).
Herald added a subscriber: cfe-commits.
Repository:
rC Clang
https://reviews.llvm.org/D43218
Files:
lib/StaticAnalyzer/Core/MemRegion.cpp
test/Analysis/region-store.cpp
test/Analysis/region_store_overflow.c
Index: test/Analysis/region-store.cpp
===================================================================
--- test/Analysis/region-store.cpp
+++ test/Analysis/region-store.cpp
@@ -25,4 +25,4 @@
Builder->setLoc(l);
return Builder->accessBase();
-}
\ No newline at end of file
+}
Index: test/Analysis/region_store_overflow.c
===================================================================
--- test/Analysis/region_store_overflow.c
+++ test/Analysis/region_store_overflow.c
@@ -0,0 +1,13 @@
+// REQUIRES: asserts
+// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -mllvm -debug %s 2>&1 | FileCheck %s
+
+int **h;
+int overflow_in_memregion(long j) {
+ for (int l = 0;; ++l) {
+ if (j - l > 0)
+ return h[j - l][0]; // no-crash
+ }
+ return 0;
+}
+// CHECK: {{.*}}
+// CHECK: MemRegion::getAsArrayOffset: offset overflowing, returning unknown
Index: lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- lib/StaticAnalyzer/Core/MemRegion.cpp
+++ lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -23,6 +23,11 @@
#include "clang/Basic/SourceManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+
+#include<functional>
+
+#define DEBUG_TYPE "MemRegion"
using namespace clang;
using namespace ento;
@@ -1149,6 +1154,36 @@
return nullptr;
}
+/// Perform a given operation on two integers, return whether it overflows.
+/// Optionally write the resulting output into \p Res.
+static bool checkedOp(
+ int64_t LHS,
+ int64_t RHS,
+ std::function<llvm::APInt(llvm::APInt *, const llvm::APInt &, bool &)> Op,
+ int64_t *Res = nullptr) {
+ llvm::APInt ALHS(/*BitSize=*/64, LHS, /*Signed=*/true);
+ llvm::APInt ARHS(/*BitSize=*/64, RHS, /*Signed=*/true);
+ bool Overflow;
+ llvm::APInt Out = Op(&ALHS, ARHS, Overflow);
+ if (!Overflow && Res)
+ *Res = Out.getSExtValue();
+ return Overflow;
+}
+
+static bool checkedAdd(
+ int64_t LHS,
+ int64_t RHS,
+ int64_t *Res=nullptr) {
+ return checkedOp(LHS, RHS, &llvm::APInt::sadd_ov, Res);
+}
+
+static bool checkedMul(
+ int64_t LHS,
+ int64_t RHS,
+ int64_t *Res=nullptr) {
+ return checkedOp(LHS, RHS, &llvm::APInt::smul_ov, Res);
+}
+
RegionRawOffset ElementRegion::getAsArrayOffset() const {
CharUnits offset = CharUnits::Zero();
const ElementRegion *ER = this;
@@ -1176,6 +1211,17 @@
}
CharUnits size = C.getTypeSizeInChars(elemType);
+
+ int64_t Mult;
+ bool Overflow = checkedAdd(i, size.getQuantity(), &Mult);
+ Overflow |= checkedMul(Mult, offset.getQuantity());
+ if (Overflow) {
+ DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
+ << "offset overflowing, returning unknown\n");
+
+ return nullptr;
+ }
+
offset += (i * size);
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D43218.135957.patch
Type: text/x-patch
Size: 2932 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180226/21403828/attachment-0001.bin>
More information about the cfe-commits
mailing list