26 using namespace clang;
30 class NonNullParamChecker
31 :
public Checker< check::PreCall > {
32 mutable std::unique_ptr<BugType> BTAttrNonNull;
33 mutable std::unique_ptr<BugType> BTNullRefArg;
39 std::unique_ptr<BugReport>
40 genReportNullAttrNonNull(
const ExplodedNode *ErrorN,
const Expr *ArgE)
const;
41 std::unique_ptr<BugReport>
42 genReportReferenceToNullPointer(
const ExplodedNode *ErrorN,
43 const Expr *ArgE)
const;
47 void NonNullParamChecker::checkPreCall(
const CallEvent &Call,
55 llvm::SmallBitVector AttrNonNull(NumArgs);
58 AttrNonNull.set(0, NumArgs);
61 for (
unsigned Val :
NonNull->args()) {
73 for (
unsigned idx = 0; idx < NumArgs; ++idx) {
77 bool haveRefTypeParam =
false;
79 haveRefTypeParam = (*TyI)->isReferenceType();
83 bool haveAttrNonNull = AttrNonNull[idx];
84 if (!haveAttrNonNull) {
87 if (idx < parms.size())
88 haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
91 if (!haveRefTypeParam && !haveAttrNonNull)
102 assert(!haveRefTypeParam || DV->getAs<
Loc>());
104 if (haveAttrNonNull && !DV->getAs<
Loc>()) {
118 assert(CSV_I != CSV->end());
121 assert(++CSV_I == CSV->end());
129 dyn_cast<InitListExpr>(CE->getInitializer()))
130 ArgE = dyn_cast<
Expr>(*(IE->begin()));
140 std::tie(stateNotNull, stateNull) = CM.
assumeDual(state, *DV);
142 if (stateNull && !stateNotNull) {
147 std::unique_ptr<BugReport> R;
149 R = genReportNullAttrNonNull(errorNode, ArgE);
150 else if (haveRefTypeParam)
151 R = genReportReferenceToNullPointer(errorNode, ArgE);
166 assert(stateNotNull);
167 state = stateNotNull;
175 std::unique_ptr<BugReport>
176 NonNullParamChecker::genReportNullAttrNonNull(
const ExplodedNode *ErrorNode,
177 const Expr *ArgE)
const {
182 BTAttrNonNull.reset(
new BugType(
183 this,
"Argument with 'nonnull' attribute passed null",
"API"));
185 auto R = llvm::make_unique<BugReport>(
187 "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode);
194 std::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
197 BTNullRefArg.reset(
new BuiltinBug(
this,
"Dereference of null pointer"));
199 auto R = llvm::make_unique<BugReport>(
200 *BTNullRefArg,
"Forming reference to null pointer", ErrorNode);
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
const Expr * getDerefExpr(const Stmt *S)
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
param_type_iterator param_type_end() const
const RecordType * getAsUnionType() const
NOTE: getAs*ArrayType are methods on ASTContext.
Describes an C or C++ initializer list.
RecordDecl * getDecl() const
Values of this type can never be null.
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
llvm::ImmutableList< SVal >::iterator iterator
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument. May be null if this expression does not appe...
virtual ArrayRef< ParmVarDecl * > parameters() const =0
const ProgramStateRef & getState() const
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
param_type_iterator param_type_begin() const
ConstraintManager & getConstraintManager()
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called. May be null.
Represents an abstract call to a function or method along a particular path.
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, bool IsArg=false, bool EnableNullFPSuppression=true)
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
llvm::mapped_iterator< ArrayRef< ParmVarDecl * >::iterator, get_type_fun > param_type_iterator