180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks//===--- NonNullParamChecker.cpp - Undefined arguments checker -*- C++ -*--===// 294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// The LLVM Compiler Infrastructure 494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// This file is distributed under the University of Illinois Open Source 694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// License. See LICENSE.TXT for details. 794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===// 994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 1080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// This defines NonNullParamChecker, which checks for arguments expected not to 1180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// be null due to: 1280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// - the corresponding parameters being declared to have nonnull attribute 1380412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// - the corresponding parameters being references; since the call would form 1480412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks// a reference to a null pointer 1594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 1694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===// 1794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 18bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "ClangSACheckers.h" 192fa67efeaf66a9332c30a026dc1c21bef6c33a6cBenjamin Kramer#include "clang/AST/Attr.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 21ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 22bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 23f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 24bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 2594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 2694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xuusing namespace clang; 279ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 2894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 29f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremeneknamespace { 3080412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksclass NonNullParamChecker 31fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose : public Checker< check::PreCall > { 32018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks mutable OwningPtr<BugType> BTAttrNonNull; 33018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks mutable OwningPtr<BugType> BTNullRefArg; 34f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic: 35bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis 36fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 37018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 38018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BugReport *genReportNullAttrNonNull(const ExplodedNode *ErrorN, 39018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const Expr *ArgE) const; 40018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BugReport *genReportReferenceToNullPointer(const ExplodedNode *ErrorN, 41018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const Expr *ArgE) const; 42f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek}; 43f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace 44f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek 4580412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid NonNullParamChecker::checkPreCall(const CallEvent &Call, 46bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis CheckerContext &C) const { 47fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose const Decl *FD = Call.getDecl(); 4894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (!FD) 4994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu return; 5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 51fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose const NonNullAttr *Att = FD->getAttr<NonNullAttr>(); 5294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 53fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose ProgramStateRef state = C.getState(); 5494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 55018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks CallEvent::param_type_iterator TyI = Call.param_type_begin(), 56018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks TyE = Call.param_type_end(); 57018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 58018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx){ 59018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 60018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // Check if the parameter is a reference. We want to report when reference 61018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // to a null pointer is passed as a paramter. 62018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks bool haveRefTypeParam = false; 63018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (TyI != TyE) { 64018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks haveRefTypeParam = (*TyI)->isReferenceType(); 65018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks TyI++; 66018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks } 67018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 68018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks bool haveAttrNonNull = Att && Att->isNonNull(idx); 69018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 70018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (!haveRefTypeParam && !haveAttrNonNull) 7194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu continue; 7294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 73018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // If the value is unknown or undefined, we can't perform this check. 74018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const Expr *ArgE = Call.getArgExpr(idx); 75fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose SVal V = Call.getArgSVal(idx); 76dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<DefinedSVal> DV = V.getAs<DefinedSVal>(); 779a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose if (!DV) 789a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose continue; 7994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 80018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // Process the case when the argument is not a location. 81018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks assert(!haveRefTypeParam || DV->getAs<Loc>()); 82018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 83018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (haveAttrNonNull && !DV->getAs<Loc>()) { 84bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek // If the argument is a union type, we want to handle a potential 85fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose // transparent_union GCC extension. 86fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose if (!ArgE) 87fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose continue; 88fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose 89fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose QualType T = ArgE->getType(); 90bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek const RecordType *UT = T->getAsUnionType(); 91bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) 92bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek continue; 93fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose 94dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie if (Optional<nonloc::CompoundVal> CSV = 955251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie DV->getAs<nonloc::CompoundVal>()) { 96bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek nonloc::CompoundVal::iterator CSV_I = CSV->begin(); 97bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek assert(CSV_I != CSV->end()); 98bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek V = *CSV_I; 995251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie DV = V.getAs<DefinedSVal>(); 100bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek assert(++CSV_I == CSV->end()); 101bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (!DV) 10242773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks continue; 10342773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks // Retrieve the corresponding expression. 10442773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks if (const CompoundLiteralExpr *CE = dyn_cast<CompoundLiteralExpr>(ArgE)) 10542773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks if (const InitListExpr *IE = 10642773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks dyn_cast<InitListExpr>(CE->getInitializer())) 10742773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks ArgE = dyn_cast<Expr>(*(IE->begin())); 10842773d64f98db0dd5cc80181c3b2d561851668f7Anna Zaks 109fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose } else { 110bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek // FIXME: Handle LazyCompoundVals? 111bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek continue; 112bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek } 113bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek } 114bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek 11594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 1168bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 11728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); 11894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 11994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (stateNull && !stateNotNull) { 12094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Generate an error node. Check for a null node in case 12194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // we cache out. 122d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *errorNode = C.generateSink(stateNull)) { 12394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 124018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BugReport *R = 0; 125018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (haveAttrNonNull) 126018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks R = genReportNullAttrNonNull(errorNode, ArgE); 127018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks else if (haveRefTypeParam) 128018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks R = genReportReferenceToNullPointer(errorNode, ArgE); 12994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 13094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Highlight the range of the argument that was null. 131fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose R->addRange(Call.getArgSourceRange(idx)); 132018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 13394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Emit the bug report. 134785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(R); 13594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 13694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 13794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Always return. Either we cached out or we just emitted an error. 13894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu return; 13994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 14094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 14194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If a pointer value passed the check we should assume that it is 14294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // indeed not null from this point forward. 14394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu assert(stateNotNull); 14494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu state = stateNotNull; 14594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 14694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 14794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If we reach here all of the arguments passed the nonnull check. 14894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If 'state' has been updated generated a new node. 1490bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 15094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu} 151bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis 15280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportNullAttrNonNull( 153018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const ExplodedNode *ErrorNode, const Expr *ArgE) const { 154018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // Lazily allocate the BugType object if it hasn't already been 155018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // created. Ownership is transferred to the BugReporter object once 156018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks // the BugReport is passed to 'EmitWarning'. 157018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (!BTAttrNonNull) 158018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BTAttrNonNull.reset(new BugType( 159018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks "Argument with 'nonnull' attribute passed null", 160018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks "API")); 161018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 162018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BugReport *R = new BugReport(*BTAttrNonNull, 163018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks "Null pointer passed as an argument to a 'nonnull' parameter", 164018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks ErrorNode); 165018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (ArgE) 166018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks bugreporter::trackNullOrUndefValue(ErrorNode, ArgE, *R); 167018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 168018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks return R; 169018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks} 170018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 17180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna ZaksBugReport *NonNullParamChecker::genReportReferenceToNullPointer( 172018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const ExplodedNode *ErrorNode, const Expr *ArgE) const { 173018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (!BTNullRefArg) 174018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BTNullRefArg.reset(new BuiltinBug("Dereference of null pointer")); 175018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 176018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks BugReport *R = new BugReport(*BTNullRefArg, 177018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks "Forming reference to null pointer", 178018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks ErrorNode); 179018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (ArgE) { 180018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks const Expr *ArgEDeref = bugreporter::getDerefExpr(ArgE); 181018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks if (ArgEDeref == 0) 182018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks ArgEDeref = ArgE; 183018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks bugreporter::trackNullOrUndefValue(ErrorNode, 184018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks ArgEDeref, 185018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks *R); 186018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks } 187018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks return R; 188018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 189018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks} 190018e9aa033ff7363797c62fc3b14669d0558284bAnna Zaks 19180412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaksvoid ento::registerNonNullParamChecker(CheckerManager &mgr) { 19280412c4e28c8247ad9c8d30d04c94938f01b21fbAnna Zaks mgr.registerChecker<NonNullParamChecker>(); 193bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis} 194