diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-02-26 21:03:06 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-02-26 21:03:06 +0000 |
commit | 585dc5db136c656cd4a0b81d652d554d39aeae30 (patch) | |
tree | b0368dea6b35f495cdcfaae7359a058f7ce2cf81 /clang/lib/StaticAnalyzer/Core/MemRegion.cpp | |
parent | 58c707d1ad44bad8a7b8aa5e5b39391200378c99 (diff) | |
download | bcm5719-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/MemRegion.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 46 |
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); } |