26 using namespace clang;
30 class NonNullParamChecker
31 :
public Checker< check::PreCall, EventDispatcher<ImplicitNullDerefEvent> > {
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;
51 llvm::SmallBitVector AttrNonNull(NumArgs);
54 AttrNonNull.set(0, NumArgs);
58 unsigned IdxAST = Idx.getASTIndex();
59 if (IdxAST >= NumArgs)
61 AttrNonNull.set(IdxAST);
67 void NonNullParamChecker::checkPreCall(
const CallEvent &Call,
78 for (
unsigned idx = 0; idx < NumArgs; ++idx) {
80 bool HasParam = idx < parms.size();
84 bool haveRefTypeParam =
85 HasParam ? parms[idx]->getType()->isReferenceType() :
false;
86 bool haveAttrNonNull = AttrNonNull[idx];
89 if (!haveAttrNonNull && HasParam)
90 haveAttrNonNull = parms[idx]->hasAttr<NonNullAttr>();
92 if (!haveAttrNonNull && !haveRefTypeParam)
102 assert(!haveRefTypeParam || DV->getAs<
Loc>());
105 if (haveAttrNonNull && !DV->getAs<
Loc>()) {
124 assert(++CSV->begin() == CSV->end());
131 if (
const auto *CE = dyn_cast<CompoundLiteralExpr>(ArgE))
132 if (
const auto *IE = dyn_cast<InitListExpr>(CE->getInitializer()))
133 ArgE = dyn_cast<
Expr>(*(IE->begin()));
138 std::tie(stateNotNull, stateNull) = CM.
assumeDual(state, *DV);
142 if (stateNull && !stateNotNull) {
145 std::unique_ptr<BugReport> R;
147 R = genReportNullAttrNonNull(errorNode, ArgE);
148 else if (haveRefTypeParam)
149 R = genReportReferenceToNullPointer(errorNode, ArgE);
167 dispatchEvent(event);
173 state = stateNotNull;
181 std::unique_ptr<BugReport>
182 NonNullParamChecker::genReportNullAttrNonNull(
const ExplodedNode *ErrorNode,
183 const Expr *ArgE)
const {
188 BTAttrNonNull.reset(
new BugType(
189 this,
"Argument with 'nonnull' attribute passed null",
"API"));
191 auto R = llvm::make_unique<BugReport>(
193 "Null pointer passed as an argument to a 'nonnull' parameter", ErrorNode);
195 bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R);
200 std::unique_ptr<BugReport> NonNullParamChecker::genReportReferenceToNullPointer(
203 BTNullRefArg.reset(
new BuiltinBug(
this,
"Dereference of null pointer"));
205 auto R = llvm::make_unique<BugReport>(
206 *BTNullRefArg,
"Forming reference to null pointer", ErrorNode);
208 const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE);
211 bugreporter::trackNullOrUndefValue(ErrorNode,
A (possibly-)qualified type.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
const RecordType * getAsUnionType() const
NOTE: getAs*ArrayType are methods on ASTContext.
const T * getAs() const
Member-template getAs<specific type>'.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
BugReporter & getBugReporter()
Values of this type can never be null.
We dereferenced a location that may be null.
virtual ArrayRef< ParmVarDecl * > parameters() const =0
Return call's formal parameters.
ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond)
Returns a pair of states (StTrue, StFalse) where the given condition is assumed to be true or false...
A single parameter index whose accessors require each use to make explicit the parameter index encodi...
Expr - This represents one expression.
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
static llvm::SmallBitVector getNonNullAttrs(const CallEvent &Call)
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
CHECKER * registerChecker(AT... Args)
Used to register checkers.
ConstraintManager & getConstraintManager()
RecordDecl * getDecl() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Dataflow Directional Tag Classes.
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
Represents an abstract call to a function or method along a particular path.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
const ProgramStateRef & getState() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.