[cfe-commits] r46843 - in /cfe/trunk/Analysis: GRConstants.cpp RValues.cpp RValues.h ValueState.cpp ValueState.h
Ted Kremenek
kremenek at apple.com
Wed Feb 6 21:48:01 PST 2008
Author: kremenek
Date: Wed Feb 6 23:48:01 2008
New Revision: 46843
URL: http://llvm.org/viewvc/llvm-project?rev=46843&view=rev
Log:
Added recording of "implicit" NULL dereferences of symbolic pointers.
Modified:
cfe/trunk/Analysis/GRConstants.cpp
cfe/trunk/Analysis/RValues.cpp
cfe/trunk/Analysis/RValues.h
cfe/trunk/Analysis/ValueState.cpp
cfe/trunk/Analysis/ValueState.h
Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46843&r1=46842&r2=46843&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Wed Feb 6 23:48:01 2008
@@ -124,6 +124,12 @@
typedef llvm::SmallPtrSet<NodeTy*,5> UninitBranchesTy;
UninitBranchesTy UninitBranches;
+ /// ImplicitNullDeref - Nodes in the ExplodedGraph that result from
+ /// taking a dereference on a symbolic pointer that may be NULL.
+ typedef llvm::SmallPtrSet<NodeTy*,5> ImplicitNullDerefTy;
+ ImplicitNullDerefTy ImplicitNullDeref;
+
+
bool StateCleaned;
ASTContext& getContext() const { return G.getContext(); }
@@ -162,6 +168,10 @@
bool isUninitControlFlow(const NodeTy* N) const {
return N->isSink() && UninitBranches.count(const_cast<NodeTy*>(N)) != 0;
}
+
+ bool isImplicitNullDeref(const NodeTy* N) const {
+ return N->isSink() && ImplicitNullDeref.count(const_cast<NodeTy*>(N)) != 0;
+ }
/// ProcessStmt - Called by GREngine. Used to generate new successor
/// nodes by processing the 'effects' of a block-level statement.
@@ -203,8 +213,10 @@
return GetValue(St, const_cast<Stmt*>(S));
}
- inline RValue GetValue(const StateTy& St, const LValue& LV) {
- return StateMgr.GetValue(St, LV);
+ inline RValue GetValue(const StateTy& St, const LValue& LV,
+ QualType* T = NULL) {
+
+ return StateMgr.GetValue(St, LV, T);
}
inline LValue GetLValue(const StateTy& St, Stmt* S) {
@@ -237,7 +249,7 @@
StateTy AssumeSymInt(StateTy St, bool Assumption, const SymIntConstraint& C,
bool& isFeasible);
- void Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
+ NodeTy* Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St);
/// Nodify - This version of Nodify is used to batch process a set of states.
/// The states are not guaranteed to be unique.
@@ -557,13 +569,16 @@
return M;
}
-void GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St) {
+GRConstants::NodeTy*
+GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred, StateTy St) {
// If the state hasn't changed, don't generate a new node.
if (St == Pred->getState())
- return;
+ return NULL;
- Dst.Add(Builder->generateNode(S, St, Pred));
+ NodeTy* N = Builder->generateNode(S, St, Pred);
+ Dst.Add(N);
+ return N;
}
void GRConstants::Nodify(NodeSet& Dst, Stmt* S, NodeTy* Pred,
@@ -756,7 +771,34 @@
const RValue& V = GetValue(St, U->getSubExpr());
const LValue& L1 = cast<LValue>(V);
- Nodify(Dst, U, N1, SetValue(St, U, GetValue(St, L1)));
+ // After a dereference, one of two possible situations arise:
+ // (1) A crash, because the pointer was NULL.
+ // (2) The pointer is not NULL, and the dereference works.
+ //
+ // We add these assumptions.
+
+ bool isFeasible;
+
+ // "Assume" that the pointer is NULL.
+ StateTy StNull = Assume(St, L1, false, isFeasible);
+
+ if (isFeasible) {
+ NodeTy* NullNode = Nodify(Dst, U, N1, StNull);
+ if (NullNode) {
+ NullNode->markAsSink();
+ ImplicitNullDeref.insert(NullNode);
+ }
+ }
+
+ // "Assume" that the pointer is Not-NULL.
+ StateTy StNotNull = Assume(St, L1, true, isFeasible);
+
+ if (isFeasible) {
+ QualType T = U->getType();
+ Nodify(Dst, U, N1, SetValue(StNotNull, U,
+ GetValue(StNotNull, L1, &T)));
+ }
+
break;
}
@@ -1208,6 +1250,11 @@
<< (void*) L.getStmt() << ' ';
L.getStmt()->printPretty(Out);
+
+ if (GraphPrintCheckerState->isImplicitNullDeref(N)) {
+ Out << "\\|Implicit-Null Dereference.\\l";
+ }
+
break;
}
Modified: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=46843&r1=46842&r2=46843&view=diff
==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (original)
+++ cfe/trunk/Analysis/RValues.cpp Wed Feb 6 23:48:01 2008
@@ -24,23 +24,35 @@
//===----------------------------------------------------------------------===//
SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
- SymbolID& X = DataToSymbol[D];
+ SymbolID& X = DataToSymbol[getKey(D)];
if (!X.isInitialized()) {
X = SymbolToData.size();
- SymbolToData.push_back(D);
+ SymbolToData.push_back(SymbolDataParmVar(D));
}
return X;
}
+SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
+ SymbolID& X = DataToSymbol[getKey(sym)];
+
+ if (!X.isInitialized()) {
+ X = SymbolToData.size();
+ SymbolToData.push_back(SymbolDataContentsOf(sym));
+ }
+
+ return X;
+}
+
QualType SymbolData::getType() const {
switch (getKind()) {
default:
assert (false && "getType() not implemented for this symbol.");
case ParmKind:
- return static_cast<ParmVarDecl*>(getPtr())->getType();
+ return cast<SymbolDataParmVar>(this)->getDecl()->getType();
+
}
}
@@ -554,7 +566,7 @@
}
}
-#if 0
+
void LValue::print(std::ostream& Out) const {
switch (getSubKind()) {
case lval::ConcreteIntKind:
@@ -576,4 +588,4 @@
break;
}
}
-#endif
+
Modified: cfe/trunk/Analysis/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.h?rev=46843&r1=46842&r2=46843&view=diff
==============================================================================
--- cfe/trunk/Analysis/RValues.h (original)
+++ cfe/trunk/Analysis/RValues.h Wed Feb 6 23:48:01 2008
@@ -61,21 +61,70 @@
}
};
+ // SymbolData: Used to record meta data about symbols.
+
class SymbolData {
+public:
+ enum Kind { UninitKind, ParmKind, ContentsOfKind };
+
+private:
uintptr_t Data;
+ Kind K;
+
+protected:
+ SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
+ SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
+
+ void* getPtr() const {
+ assert (K != UninitKind);
+ return reinterpret_cast<void*>(Data);
+ }
+
+ uintptr_t getInt() const {
+ assert (K != UninitKind);
+ return Data;
+ }
+
public:
- enum Kind { ParmKind = 0x0, Mask = 0x3 };
+ SymbolData() : Data(0), K(UninitKind) {}
- SymbolData(ParmVarDecl* D)
- : Data(reinterpret_cast<uintptr_t>(D) | ParmKind) {}
+ Kind getKind() const { return K; }
+
+ inline bool operator==(const SymbolData& R) const {
+ return K == R.K && Data == R.Data;
+ }
- inline Kind getKind() const { return (Kind) (Data & Mask); }
- inline void* getPtr() const { return reinterpret_cast<void*>(Data & ~Mask); }
- inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
+ QualType getType() const;
- QualType getType() const;
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData*) { return true; }
};
+
+class SymbolDataParmVar : public SymbolData {
+public:
+ SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
+
+ ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData* D) {
+ return D->getKind() == ParmKind;
+ }
+};
+
+class SymbolDataContentsOf : public SymbolData {
+public:
+ SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
+
+ SymbolID getSymbol() const { return (SymbolID) getInt(); }
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData* D) {
+ return D->getKind() == ContentsOfKind;
+ }
+};
+
+ // Constraints on symbols. Usually wrapped by RValues.
class SymIntConstraint : public llvm::FoldingSetNode {
SymbolID Symbol;
@@ -112,13 +161,22 @@
typedef llvm::DenseMap<void*,SymbolID> MapTy;
MapTy DataToSymbol;
+ void* getKey(void* P) const {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
+ }
+
+ void* getKey(SymbolID sym) const {
+ return reinterpret_cast<void*>((uintptr_t) (sym << 1));
+ }
+
public:
SymbolManager();
~SymbolManager();
SymbolID getSymbol(ParmVarDecl* D);
+ SymbolID getContentsOfSymbol(SymbolID sym);
- inline SymbolData getSymbolData(SymbolID ID) const {
+ inline const SymbolData& getSymbolData(SymbolID ID) const {
assert (ID < SymbolToData.size());
return SymbolToData[ID];
}
@@ -176,30 +234,6 @@
} // end clang namespace
//==------------------------------------------------------------------------==//
-// Casting machinery to get cast<> and dyn_cast<> working with SymbolData.
-//==------------------------------------------------------------------------==//
-
-namespace llvm {
-
- template<> inline bool
- isa<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
- return V.getKind() == clang::SymbolData::ParmKind;
- }
-
- template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
- typedef const clang::ParmVarDecl* ret_type;
- };
-
- template<> struct simplify_type<clang::SymbolData> {
- typedef void* SimpleType;
- static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
- return V.getPtr();
- }
- };
-
-} // end llvm namespace
-
-//==------------------------------------------------------------------------==//
// Base RValue types.
//==------------------------------------------------------------------------==//
@@ -323,7 +357,7 @@
NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const;
public:
-// void print(std::ostream& Out) const;
+ void print(std::ostream& Out) const;
RValue EvalBinaryOp(ValueManager& ValMgr, BinaryOperator::Opcode Op,
const LValue& RHS) const;
Modified: cfe/trunk/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.cpp?rev=46843&r1=46842&r2=46843&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.cpp (original)
+++ cfe/trunk/Analysis/ValueState.cpp Wed Feb 6 23:48:01 2008
@@ -33,7 +33,8 @@
-RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV) {
+RValue ValueStateManager::GetValue(const StateTy& St, const LValue& LV,
+ QualType* T) {
if (isa<InvalidValue>(LV))
return InvalidValue();
@@ -44,6 +45,19 @@
return T ? T->getValue().second : InvalidValue();
}
+
+ // FIXME: We should bind how far a "ContentsOf" will go...
+
+ case lval::SymbolValKind: {
+ const lval::SymbolVal& SV = cast<lval::SymbolVal>(LV);
+ assert (T);
+
+ if (T->getTypePtr()->isPointerType())
+ return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
+ else
+ return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol()));
+ }
+
default:
assert (false && "Invalid LValue.");
break;
Modified: cfe/trunk/Analysis/ValueState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.h?rev=46843&r1=46842&r2=46843&view=diff
==============================================================================
--- cfe/trunk/Analysis/ValueState.h (original)
+++ cfe/trunk/Analysis/ValueState.h Wed Feb 6 23:48:01 2008
@@ -264,7 +264,7 @@
StateTy SetValue(StateTy St, const LValue& LV, const RValue& V);
RValue GetValue(const StateTy& St, Stmt* S, bool* hasVal = NULL);
- RValue GetValue(const StateTy& St, const LValue& LV);
+ RValue GetValue(const StateTy& St, const LValue& LV, QualType* T = NULL);
LValue GetLValue(const StateTy& St, Stmt* S);
More information about the cfe-commits
mailing list