23#include "llvm/ADT/StringExtras.h"
24#include "llvm/Support/raw_ostream.h"
31class CallAndMessageChecker
32 :
public Checker<check::PreObjCMessage, check::ObjCMessageNil,
34 const BugType CallNullBug{
35 this,
"Called function pointer is null (null dereference)"};
36 const BugType CallUndefBug{
37 this,
"Called function pointer is an uninitialized pointer value"};
38 const BugType CXXCallNullBug{
this,
"Called C++ object pointer is null"};
39 const BugType CXXCallUndefBug{
this,
40 "Called C++ object pointer is uninitialized"};
41 const BugType CallArgBug{
this,
"Uninitialized argument value"};
42 const BugType CXXDeleteUndefBug{
this,
"Uninitialized argument value"};
43 const BugType MsgUndefBug{
44 this,
"Receiver in message expression is an uninitialized value"};
45 const BugType ObjCPropUndefBug{
46 this,
"Property access on an uninitialized object pointer"};
47 const BugType ObjCSubscriptUndefBug{
48 this,
"Subscript access on an uninitialized object pointer"};
49 const BugType MsgArgBug{
this,
"Uninitialized argument value"};
50 const BugType MsgRetBug{
this,
"Receiver in message expression is 'nil'"};
51 const BugType CallFewArgsBug{
this,
"Function call with too few arguments"};
70 CK_CXXDeallocationArg,
71 CK_ArgInitializedness,
72 CK_ArgPointeeInitializedness,
78 bool ChecksEnabled[CK_NumCheckKinds] = {
false};
80 void checkPreObjCMessage(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
85 void checkObjCMessageNil(
const ObjCMethodCall &msg, CheckerContext &
C)
const;
87 void checkPreCall(
const CallEvent &
Call, CheckerContext &
C)
const;
109 bool PreVisitProcessArg(CheckerContext &
C, SVal
V, SourceRange ArgRange,
110 const Expr *ArgEx,
int ArgumentNumber,
111 bool CheckUninitFields,
const CallEvent &
Call,
113 const ParmVarDecl *ParamDecl)
const;
115 static void emitBadCall(
const BugType &BT, CheckerContext &
C,
117 void emitNilReceiverBug(CheckerContext &
C,
const ObjCMethodCall &msg,
118 ExplodedNode *N)
const;
120 void HandleNilReceiver(CheckerContext &
C,
122 const ObjCMethodCall &msg)
const;
124 bool uninitRefOrPointer(CheckerContext &
C, SVal
V, SourceRange ArgRange,
125 const Expr *ArgEx,
const BugType &BT,
126 const ParmVarDecl *ParamDecl,
127 int ArgumentNumber)
const;
133 ExplodedNode *N =
C.generateErrorNode();
137 auto R = std::make_unique<PathSensitiveBugReport>(BT, BT.
getDescription(), N);
144 C.emitReport(std::move(R));
149 llvm::raw_svector_ostream &Os) {
150 switch (
Call.getKind()) {
155 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
156 <<
" argument in message expression is an uninitialized value";
159 assert(Msg.
isSetter() &&
"Getters have no args");
160 Os <<
"Argument for property setter is an uninitialized value";
163 if (Msg.
isSetter() && (ArgumentNumber == 0))
164 Os <<
"Argument for subscript setter is an uninitialized value";
166 Os <<
"Subscript index is an uninitialized value";
169 llvm_unreachable(
"Unknown message kind.");
172 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
173 <<
" block call argument is an uninitialized value";
176 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
177 <<
" function call argument is an uninitialized value";
182bool CallAndMessageChecker::uninitRefOrPointer(
183 CheckerContext &
C, SVal
V, SourceRange ArgRange,
const Expr *ArgEx,
184 const BugType &BT,
const ParmVarDecl *ParamDecl,
int ArgumentNumber)
const {
188 if (!ChecksEnabled[CK_ArgPointeeInitializedness])
198 SmallString<200> Buf;
199 llvm::raw_svector_ostream Os(Buf);
202 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
203 <<
" function call argument is a pointer to uninitialized value";
205 Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
206 <<
" function call argument is an uninitialized value";
213 if (
const MemRegion *SValMemRegion =
V.getAsRegion()) {
215 const SVal PSV = State->getSVal(SValMemRegion,
C.getASTContext().CharTy);
217 if (ExplodedNode *N =
C.generateErrorNode()) {
218 auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
219 R->addRange(ArgRange);
223 C.emitReport(std::move(R));
232class FindUninitializedField {
234 SmallVector<const FieldDecl *, 10> FieldChain;
237 StoreManager &StoreMgr;
238 MemRegionManager &MrMgr;
242 FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
244 : StoreMgr(storeMgr), MrMgr(mrMgr), store(
s) {}
246 bool Find(
const TypedValueRegion *R) {
249 const RecordDecl *RD = RT->getOriginalDecl()->getDefinition();
250 assert(RD &&
"Referred record has no definition");
251 for (
const auto *I : RD->
fields()) {
252 if (I->isUnnamedBitField())
255 FieldChain.push_back(I);
261 SVal
V = StoreMgr.
getBinding(store, loc::MemRegionVal(FR));
265 FieldChain.pop_back();
274bool CallAndMessageChecker::PreVisitProcessArg(
275 CheckerContext &
C, SVal
V, SourceRange ArgRange,
const Expr *ArgEx,
276 int ArgumentNumber,
bool CheckUninitFields,
const CallEvent &
Call,
277 const BugType &BT,
const ParmVarDecl *ParamDecl)
const {
278 if (uninitRefOrPointer(
C,
V, ArgRange, ArgEx, BT, ParamDecl, ArgumentNumber))
282 if (!ChecksEnabled[CK_ArgInitializedness]) {
286 if (ExplodedNode *N =
C.generateErrorNode()) {
288 SmallString<200> Buf;
289 llvm::raw_svector_ostream Os(Buf);
291 auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);
293 R->addRange(ArgRange);
296 C.emitReport(std::move(R));
301 if (!CheckUninitFields)
304 if (
auto LV =
V.getAs<nonloc::LazyCompoundVal>()) {
305 const LazyCompoundValData *D = LV->getCVData();
306 FindUninitializedField F(
C.getState()->getStateManager().getStoreManager(),
307 C.getSValBuilder().getRegionManager(),
311 if (!ChecksEnabled[CK_ArgInitializedness]) {
315 if (ExplodedNode *N =
C.generateErrorNode()) {
316 SmallString<512> Str;
317 llvm::raw_svector_ostream os(Str);
318 os <<
"Passed-by-value struct argument contains uninitialized data";
320 if (F.FieldChain.size() == 1)
321 os <<
" (e.g., field: '" << *F.FieldChain[0] <<
"')";
323 os <<
" (e.g., via the field chain: '";
325 for (SmallVectorImpl<const FieldDecl *>::iterator
326 DI = F.FieldChain.begin(), DE = F.FieldChain.end(); DI!=DE;++DI){
337 auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N);
338 R->addRange(ArgRange);
344 C.emitReport(std::move(R));
357 const LocationContext *LCtx =
C.getLocationContext();
358 SVal L = State->getSVal(Callee, LCtx);
361 if (!ChecksEnabled[CK_FunctionPointer]) {
365 emitBadCall(CallUndefBug,
C, Callee);
370 std::tie(StNonNull, StNull) = State->assume(L.
castAs<DefinedOrUnknownSVal>());
372 if (StNull && !StNonNull) {
373 if (!ChecksEnabled[CK_FunctionPointer]) {
377 emitBadCall(CallNullBug,
C, Callee);
389 unsigned Params =
Call.parameters().size();
390 if (
Call.getNumArgs() >= Params)
393 if (!ChecksEnabled[CK_ParameterCount]) {
398 ExplodedNode *N =
C.generateErrorNode();
402 SmallString<512> Str;
403 llvm::raw_svector_ostream os(Str);
410 os <<
"taking " << Params <<
" argument" << (Params == 1 ?
"" :
"s")
411 <<
" is called with fewer (" <<
Call.getNumArgs() <<
")";
414 std::make_unique<PathSensitiveBugReport>(CallFewArgsBug, os.str(), N));
419 const CXXInstanceCall *CC, CheckerContext &
C,
ProgramStateRef State)
const {
423 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
432 std::tie(StNonNull, StNull) = State->assume(
V.castAs<DefinedOrUnknownSVal>());
434 if (StNull && !StNonNull) {
435 if (!ChecksEnabled[CK_CXXThisMethodCall]) {
447CallAndMessageChecker::checkCXXDeallocation(
const CXXDeallocatorCall *DC,
456 if (!ChecksEnabled[CK_CXXDeallocationArg]) {
462 ExplodedNode *N =
C.generateErrorNode();
466 Desc =
"Argument to 'delete[]' is uninitialized";
468 Desc =
"Argument to 'delete' is uninitialized";
469 auto R = std::make_unique<PathSensitiveBugReport>(CXXDeleteUndefBug, Desc, N);
471 C.emitReport(std::move(R));
484 const bool checkUninitFields =
485 !(
C.getAnalysisManager().shouldInlineCall() && (D && D->
getBody()));
489 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
490 for (
unsigned i = 0, e =
Call.getNumArgs(); i != e; ++i) {
491 const ParmVarDecl *ParamDecl =
nullptr;
492 if (FD && i < FD->getNumParams())
494 if (PreVisitProcessArg(
C,
Call.getArgSVal(i),
Call.getArgSourceRange(i),
495 Call.getArgExpr(i), i, checkUninitFields,
Call, BT,
502void CallAndMessageChecker::checkPreCall(
const CallEvent &
Call,
503 CheckerContext &
C)
const {
506 if (
const CallExpr *CE = dyn_cast_or_null<CallExpr>(
Call.getOriginExpr()))
507 State = checkFunctionPointerCall(CE,
C, State);
513 State = checkParameterCount(
Call,
C, State);
518 if (
const auto *CC = dyn_cast<CXXInstanceCall>(&
Call))
519 State = checkCXXMethodCall(CC,
C, State);
524 if (
const auto *DC = dyn_cast<CXXDeallocatorCall>(&
Call))
525 State = checkCXXDeallocation(DC,
C, State);
530 State = checkArgInitializedness(
Call,
C, State);
533 C.addTransition(State);
536void CallAndMessageChecker::checkPreObjCMessage(
const ObjCMethodCall &msg,
537 CheckerContext &
C)
const {
540 if (!ChecksEnabled[CK_UndefReceiver]) {
544 if (ExplodedNode *N =
C.generateErrorNode()) {
545 const BugType *BT =
nullptr;
551 BT = &ObjCPropUndefBug;
554 BT = &ObjCSubscriptUndefBug;
557 assert(BT &&
"Unknown message kind.");
559 auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->
getDescription(), N);
566 C.emitReport(std::move(R));
572void CallAndMessageChecker::checkObjCMessageNil(
const ObjCMethodCall &msg,
573 CheckerContext &
C)
const {
574 HandleNilReceiver(
C,
C.getState(), msg);
577void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &
C,
578 const ObjCMethodCall &msg,
579 ExplodedNode *N)
const {
580 if (!ChecksEnabled[CK_NilReceiver]) {
589 SmallString<200> buf;
590 llvm::raw_svector_ostream os(buf);
591 os <<
"The receiver of message '";
595 os <<
", which results in forming a null reference";
597 os <<
" and returns a value of type '";
599 os <<
"' that will be garbage";
603 std::make_unique<PathSensitiveBugReport>(MsgRetBug, os.str(), N);
609 C.emitReport(std::move(report));
613 return (triple.getVendor() == llvm::Triple::Apple &&
614 (triple.isiOS() || triple.isWatchOS() ||
615 !triple.isMacOSXVersionLT(10,5)));
618void CallAndMessageChecker::HandleNilReceiver(CheckerContext &
C,
620 const ObjCMethodCall &Msg)
const {
621 ASTContext &Ctx =
C.getASTContext();
627 const LocationContext *LCtx =
C.getLocationContext();
629 if (CanRetTy->isStructureOrClassType()) {
631 SVal
V =
C.getSValBuilder().makeZeroVal(RetTy);
637 if (CanRetTy != Ctx.
VoidTy &&
C.getLocationContext()->getParentMap()
644 (voidPtrSize < returnTypeSize &&
651 if (ExplodedNode *N =
C.generateErrorNode(state))
652 emitNilReceiverBug(
C, Msg, N);
669 SVal
V =
C.getSValBuilder().makeZeroVal(RetTy);
674 C.addTransition(state);
677void ento::registerCallAndMessageChecker(CheckerManager &Mgr) {
678 CallAndMessageChecker *Chk = Mgr.
registerChecker<CallAndMessageChecker>();
680#define QUERY_CHECKER_OPTION(OPTION) \
681 Chk->ChecksEnabled[CallAndMessageChecker::CK_##OPTION] = \
682 Mgr.getAnalyzerOptions().getCheckerBooleanOption( \
683 Mgr.getCurrentCheckerName(), #OPTION);
695bool ento::shouldRegisterCallAndMessageChecker(
const CheckerManager &) {
#define QUERY_CHECKER_OPTION(OPTION)
static bool supportsNilWithFloatRet(const llvm::Triple &triple)
static void describeUninitializedArgumentInCall(const CallEvent &Call, int ArgumentNumber, llvm::raw_svector_ostream &Os)
Defines the clang::Expr interface and subclasses for C++ expressions.
__device__ __2f16 float __ockl_bool s
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CanQualType UnsignedLongLongTy
const TargetInfo & getTargetInfo() const
bool isArrayFormAsWritten() const
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
const ParmVarDecl * getParamDecl(unsigned i) const
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Selector getSelector() const
SourceRange getReceiverRange() const
Source range of the receiver.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isConstQualified() const
Determine whether this type is const-qualified.
field_range fields() const
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isStructureType() const
bool isPointerType() const
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
const RecordType * getAsStructureType() const
StringRef getDescription() const
const CXXDeleteExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
virtual SVal getCXXThisVal() const
Returns the value of the implicit 'this' object.
virtual const Expr * getCXXThisExpr() const
Returns the expression representing the implicit 'this' object.
Represents an abstract call to a function or method along a particular path.
QualType getResultType() const
Returns the result type, adjusted for references.
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
const void * getStore() const
It might return null.
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
const FieldRegion * getFieldRegion(const FieldDecl *FD, const SubRegion *SuperRegion)
getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.
Represents any expression that calls an Objective-C method.
ObjCMessageKind getMessageKind() const
Returns how the message was written in the source (property access, subscript, or explicit message se...
bool isSetter() const
Returns true if this property access or subscript is a setter (has the form of an assignment).
const ObjCMessageExpr * getOriginExpr() const override
Returns the expression whose value will be the result of this call.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0
Return the value bound to specified location in a given state.
virtual QualType getValueType() const =0
Defines the clang::TargetInfo interface.
const Expr * getDerefExpr(const Stmt *S)
Given that expression S represents a pointer that would be dereferenced, try to find a sub-expression...
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
U cast(CodeGen::Address addr)