194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===--- AttrNonNullChecker.h - 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// 10d2592a34a059e7cbb2b11dc53649ac4912422909Argyrios Kyrtzidis// This defines AttrNonNullChecker, a builtin check in ExprEngine that 1194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// performs checks for arguments declared to have nonnull attribute. 1294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu// 1394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu//===----------------------------------------------------------------------===// 1494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 15bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "ClangSACheckers.h" 16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 17bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 19bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 209b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 2194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 2294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xuusing namespace clang; 239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 2494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 25f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremeneknamespace { 26ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass AttrNonNullChecker 27fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose : public Checker< check::PreCall > { 286f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith mutable OwningPtr<BugType> BT; 29f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenekpublic: 30bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis 31fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 32f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek}; 33f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek} // end anonymous namespace 34f493f49fae3ab242ae055ae00b24fa5512655e15Ted Kremenek 35fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rosevoid AttrNonNullChecker::checkPreCall(const CallEvent &Call, 36bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis CheckerContext &C) const { 37fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose const Decl *FD = Call.getDecl(); 3894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (!FD) 3994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu return; 4094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 41fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose const NonNullAttr *Att = FD->getAttr<NonNullAttr>(); 4294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (!Att) 4394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu return; 4494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 45fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose ProgramStateRef state = C.getState(); 4694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 47fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose // Iterate through the arguments of CE and check them for null. 48fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose for (unsigned idx = 0, count = Call.getNumArgs(); idx != count; ++idx) { 4994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (!Att->isNonNull(idx)) 5094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu continue; 5194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 52fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose SVal V = Call.getArgSVal(idx); 539a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose DefinedSVal *DV = dyn_cast<DefinedSVal>(&V); 549a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose 559a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose // If the value is unknown or undefined, we can't perform this check. 569a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose if (!DV) 579a126850968b0aa25f7c6f214e7309e33f2d800aJordy Rose continue; 5894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 59bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (!isa<Loc>(*DV)) { 60bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek // If the argument is a union type, we want to handle a potential 61fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose // transparent_union GCC extension. 62fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose const Expr *ArgE = Call.getArgExpr(idx); 63fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose if (!ArgE) 64fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose continue; 65fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose 66fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose QualType T = ArgE->getType(); 67bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek const RecordType *UT = T->getAsUnionType(); 68bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) 69bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek continue; 70fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose 71bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (nonloc::CompoundVal *CSV = dyn_cast<nonloc::CompoundVal>(DV)) { 72bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek nonloc::CompoundVal::iterator CSV_I = CSV->begin(); 73bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek assert(CSV_I != CSV->end()); 74bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek V = *CSV_I; 75bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek DV = dyn_cast<DefinedSVal>(&V); 76bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek assert(++CSV_I == CSV->end()); 77bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek if (!DV) 78bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek continue; 79fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose } else { 80bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek // FIXME: Handle LazyCompoundVals? 81bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek continue; 82bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek } 83bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek } 84bb0ba0bca7896e76f8ce9b709ee881cc505e4d5eTed Kremenek 8594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 868bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 8728f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); 8894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 8994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (stateNull && !stateNotNull) { 9094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Generate an error node. Check for a null node in case 9194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // we cache out. 92d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *errorNode = C.generateSink(stateNull)) { 9394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 9494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Lazily allocate the BugType object if it hasn't already been 9594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // created. Ownership is transferred to the BugReporter object once 9694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // the BugReport is passed to 'EmitWarning'. 9794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu if (!BT) 98bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis BT.reset(new BugType("Argument with 'nonnull' attribute passed null", 99bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis "API")); 10094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 101e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks BugReport *R = 10250bbc165b063155cc23c360deb7b865502e068e2Anna Zaks new BugReport(*BT, "Null pointer passed as an argument to a " 10350bbc165b063155cc23c360deb7b865502e068e2Anna Zaks "'nonnull' parameter", errorNode); 10494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 10594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Highlight the range of the argument that was null. 106fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose R->addRange(Call.getArgSourceRange(idx)); 107fe6a011a113b3ddcb32f42af152d7476054e7f79Jordan Rose if (const Expr *ArgE = Call.getArgExpr(idx)) 108a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose bugreporter::trackNullOrUndefValue(errorNode, ArgE, *R); 10994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Emit the bug report. 11094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu C.EmitReport(R); 11194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 11294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 11394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // Always return. Either we cached out or we just emitted an error. 11494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu return; 11594943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 11694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 11794943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If a pointer value passed the check we should assume that it is 11894943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // indeed not null from this point forward. 11994943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu assert(stateNotNull); 12094943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu state = stateNotNull; 12194943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu } 12294943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu 12394943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If we reach here all of the arguments passed the nonnull check. 12494943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu // If 'state' has been updated generated a new node. 1250bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 12694943b6d913718216a95a91864040ffc11a1d779Zhongxing Xu} 127bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis 128bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidisvoid ento::registerAttrNonNullChecker(CheckerManager &mgr) { 129bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis mgr.registerChecker<AttrNonNullChecker>(); 130bd90076671c8012244bb7e3fd84b6789e47cb199Argyrios Kyrtzidis} 131