mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 19:49:36 +00:00
[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
This commit is contained in:
parent
788087f5f8
commit
0cba5549ef
@ -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
|
||||
|
@ -1,6 +1,5 @@
|
||||
// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -verify %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
int **h;
|
||||
int overflow_in_memregion(long j) {
|
||||
for (int l = 0;; ++l) {
|
||||
@ -9,3 +8,9 @@ int overflow_in_memregion(long j) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rdar39593879(long long *d) {
|
||||
long e, f;
|
||||
e = f = d[1]; // no-crash
|
||||
for (; d[e];) f-- > 0; // expected-warning{{relational comparison result unused}};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user