summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-06-13 18:32:19 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-06-13 18:32:19 +0000
commit0cba5549ef595381512609c16097c18006562335 (patch)
tree0c240f59b0ab9a7b50c277dd0f6fdd5abb6f56e4 /clang/lib/StaticAnalyzer/Core/MemRegion.cpp
parent788087f5f8013b4b4793754104970e980967eb24 (diff)
downloadbcm5719-llvm-0cba5549ef595381512609c16097c18006562335.tar.gz
bcm5719-llvm-0cba5549ef595381512609c16097c18006562335.zip
[analyzer] Fix offset overflow check in MemRegion
rdar://39593879 https://bugs.llvm.org/show_bug.cgi?id=37142 Differential Revision: https://reviews.llvm.org/D48139 llvm-svn: 334636
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/MemRegion.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/MemRegion.cpp50
1 files changed, 8 insertions, 42 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
index 5dfe3c95b90..9507ea0e088 100644
--- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -41,6 +41,7 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CheckedArithmetic.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -1181,38 +1182,8 @@ 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();
+ int64_t offset = 0;
const ElementRegion *ER = this;
const MemRegion *superR = nullptr;
ASTContext &C = getContext();
@@ -1224,7 +1195,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
// FIXME: generalize to symbolic offsets.
SVal index = ER->getIndex();
- if (Optional<nonloc::ConcreteInt> CI = index.getAs<nonloc::ConcreteInt>()) {
+ if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
// Update the offset.
int64_t i = CI->getValue().getSExtValue();
@@ -1237,20 +1208,15 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
break;
}
- CharUnits size = C.getTypeSizeInChars(elemType);
-
- int64_t Mult;
- bool Overflow = checkedAdd(i, size.getQuantity(), &Mult);
- if (!Overflow)
- Overflow = checkedMul(Mult, offset.getQuantity());
- if (Overflow) {
+ int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
+ if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
+ offset = *NewOffset;
+ } else {
LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
<< "offset overflowing, returning unknown\n");
return nullptr;
}
-
- offset += (i * size);
}
// Go to the next ElementRegion (if any).
@@ -1262,7 +1228,7 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
}
assert(superR && "super region cannot be NULL");
- return RegionRawOffset(superR, offset);
+ return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
}
/// Returns true if \p Base is an immediate base class of \p Child
OpenPOWER on IntegriCloud