Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,14 @@ ANALYZER_OPTION(
"behavior, set the option to 0.",
5)

ANALYZER_OPTION(
unsigned, RegionStoreMaxBindingFanOut, "region-store-max-binding-fanout",
"This option limits how many sub-bindings a single binding operation can "
"scatter into. For example, binding an array would scatter into binding "
"each individual element. Setting this to zero means unlimited, but then "
"modelling large array initializers may take proportional time to their "
"size.", 100)

//===----------------------------------------------------------------------===//
// String analyzer options.
//===----------------------------------------------------------------------===//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,13 +659,13 @@ class ExprEngine {
SVal Loc, SVal Val,
const LocationContext *LCtx);

public:
/// A simple wrapper when you only need to notify checkers of pointer-escape
/// of some values.
ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef<SVal> Vs,
PointerEscapeKind K,
const CallEvent *Call = nullptr) const;

public:
// FIXME: 'tag' should be removed, and a LocationContext should be used
// instead.
// FIXME: Comment on the meaning of the arguments, when 'St' may not
Expand Down
10 changes: 9 additions & 1 deletion clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ class SymbolReaper;

using InvalidatedSymbols = llvm::DenseSet<SymbolRef>;

struct BindResult {
StoreRef ResultingStore;

// If during the bind operation we exhaust the allowed binding budget, we set
// this to the beginning of the escaped part of the region.
llvm::SmallVector<SVal, 0> FailedToBindValues;
};

class StoreManager {
protected:
SValBuilder &svalBuilder;
Expand Down Expand Up @@ -105,7 +113,7 @@ class StoreManager {
/// \return A StoreRef object that contains the same
/// bindings as \c store with the addition of having the value specified
/// by \c val bound to the location given for \c loc.
virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
virtual BindResult Bind(Store store, Loc loc, SVal val) = 0;

/// Return a store with the specified value bound to all sub-regions of the
/// region. The region must not have previous bindings. If you need to
Expand Down
18 changes: 14 additions & 4 deletions clang/lib/StaticAnalyzer/Core/ProgramState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,23 @@ ProgramStateRef ProgramState::bindLoc(Loc LV,
const LocationContext *LCtx,
bool notifyChanges) const {
ProgramStateManager &Mgr = getStateManager();
ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
LV, V));
ExprEngine &Eng = Mgr.getOwningEngine();
BindResult BindRes = Mgr.StoreMgr->Bind(getStore(), LV, V);
ProgramStateRef State = makeWithStore(BindRes.ResultingStore);
const MemRegion *MR = LV.getAsRegion();

// We must always notify the checkers for failing binds because otherwise they
// may keep stale traits for these symbols.
// Eg., Malloc checker may report leaks if we failed to bind that symbol.
if (!BindRes.FailedToBindValues.empty()) {
State =
Eng.escapeValues(State, BindRes.FailedToBindValues, PSK_EscapeOnBind);
}

if (MR && notifyChanges)
return Mgr.getOwningEngine().processRegionChange(newState, MR, LCtx);
return Eng.processRegionChange(State, MR, LCtx);

return newState;
return State;
}

ProgramStateRef
Expand Down
Loading