Revert "Revert "[analyzer] Quickfix: do not overflow in calculating offset in RegionManager""

This reverts commit c4cc41166d93178a3ddd4b2b5a685cf74a459247.

Revert and fix uninitialized read.

llvm-svn: 326152
This commit is contained in:
George Karpenkov 2018-02-27 00:05:04 +00:00
parent a459dab937
commit 50339a2e84
3 changed files with 61 additions and 1 deletions

View File

@ -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,18 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
}
CharUnits size = C.getTypeSizeInChars(elemType);
int64_t Mult;
bool Overflow = checkedAdd(i, size.getQuantity(), &Mult);
if (!Overflow)
Overflow = checkedMul(Mult, offset.getQuantity());
if (Overflow) {
DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
<< "offset overflowing, returning unknown\n");
return nullptr;
}
offset += (i * size);
}

View File

@ -25,4 +25,4 @@ int radar13445834(Derived *Builder, Loc l) {
Builder->setLoc(l);
return Builder->accessBase();
}
}

View File

@ -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