summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-02-26 21:03:06 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-02-26 21:03:06 +0000
commit585dc5db136c656cd4a0b81d652d554d39aeae30 (patch)
treeb0368dea6b35f495cdcfaae7359a058f7ce2cf81 /clang/lib/StaticAnalyzer/Core
parent58c707d1ad44bad8a7b8aa5e5b39391200378c99 (diff)
downloadbcm5719-llvm-585dc5db136c656cd4a0b81d652d554d39aeae30.tar.gz
bcm5719-llvm-585dc5db136c656cd4a0b81d652d554d39aeae30.zip
[analyzer] Quickfix: do not overflow in calculating offset in RegionManager
Addresses https://bugs.llvm.org/show_bug.cgi?id=36206 rdar://37159026 A proper fix would be much harder, and would involve changing the appropriate code in ExprEngine to be aware of the size limitations of the type used for addressing. Differential Revision: https://reviews.llvm.org/D43218 llvm-svn: 326122
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core')
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index aa54544fa7d..2f77524f68a 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/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 @@ const SymbolicRegion *MemRegion::getSymbolicBase() const {
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 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
}
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);
}
OpenPOWER on IntegriCloud