1c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu//===-- StreamChecker.cpp -----------------------------------------*- C++ -*--// 2c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// 3c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// The LLVM Compiler Infrastructure 4c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// 5c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// This file is distributed under the University of Illinois Open Source 6c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// License. See LICENSE.TXT for details. 7c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// 8c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu//===----------------------------------------------------------------------===// 9c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// 10c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// This file defines checkers that model and check stream handling functions. 11c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu// 12c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu//===----------------------------------------------------------------------===// 13c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 14a0decc9a2481f938e1675b4f7bbd58761a882a36Argyrios Kyrtzidis#include "ClangSACheckers.h" 1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 17695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 18699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 1918c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 2018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 219b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 22c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu#include "llvm/ADT/ImmutableMap.h" 23c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 24c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xuusing namespace clang; 259ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 26c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 27c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xunamespace { 28c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 299843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xustruct StreamState { 30766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu enum Kind { Opened, Closed, OpenFailed, Escaped } K; 319843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu const Stmt *S; 329843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 339843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu StreamState(Kind k, const Stmt *s) : K(k), S(s) {} 349843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 359843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu bool isOpened() const { return K == Opened; } 369843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu bool isClosed() const { return K == Closed; } 37fae962200efef618d1c24c14b9c3fed25876f059Chris Lattner //bool isOpenFailed() const { return K == OpenFailed; } 38fae962200efef618d1c24c14b9c3fed25876f059Chris Lattner //bool isEscaped() const { return K == Escaped; } 399843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 409843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu bool operator==(const StreamState &X) const { 419843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu return K == X.K && S == X.S; 429843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 439843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 449843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu static StreamState getOpened(const Stmt *s) { return StreamState(Opened, s); } 459843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu static StreamState getClosed(const Stmt *s) { return StreamState(Closed, s); } 4647dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu static StreamState getOpenFailed(const Stmt *s) { 4747dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu return StreamState(OpenFailed, s); 4847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu } 49766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu static StreamState getEscaped(const Stmt *s) { 50766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu return StreamState(Escaped, s); 51766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 529843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 539843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu void Profile(llvm::FoldingSetNodeID &ID) const { 549843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu ID.AddInteger(K); 559843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu ID.AddPointer(S); 569843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 579843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu}; 589843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 59ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidisclass StreamChecker : public Checker<eval::Call, 60f34a5791c5c9df0348714e275adb09b8cf858460Jordan Rose check::DeadSymbols > { 61699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, 62699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis *II_fwrite, 63c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos, 64c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu *II_clearerr, *II_feof, *II_ferror, *II_fileno; 65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines mutable std::unique_ptr<BuiltinBug> BT_nullfp, BT_illegalwhence, 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_doubleclose, BT_ResourceLeak; 67c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 68c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xupublic: 6923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu StreamChecker() 706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines : II_fopen(nullptr), II_tmpfile(nullptr), II_fclose(nullptr), 716bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines II_fread(nullptr), II_fwrite(nullptr), II_fseek(nullptr), 726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines II_ftell(nullptr), II_rewind(nullptr), II_fgetpos(nullptr), 736bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines II_fsetpos(nullptr), II_clearerr(nullptr), II_feof(nullptr), 746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines II_ferror(nullptr), II_fileno(nullptr) {} 75c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 76699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis bool evalCall(const CallExpr *CE, CheckerContext &C) const; 77699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 78c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 79c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xuprivate: 80699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fopen(CheckerContext &C, const CallExpr *CE) const; 81699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Tmpfile(CheckerContext &C, const CallExpr *CE) const; 82699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fclose(CheckerContext &C, const CallExpr *CE) const; 83699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fread(CheckerContext &C, const CallExpr *CE) const; 84699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fwrite(CheckerContext &C, const CallExpr *CE) const; 85699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fseek(CheckerContext &C, const CallExpr *CE) const; 86699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Ftell(CheckerContext &C, const CallExpr *CE) const; 87699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Rewind(CheckerContext &C, const CallExpr *CE) const; 88699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fgetpos(CheckerContext &C, const CallExpr *CE) const; 89699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fsetpos(CheckerContext &C, const CallExpr *CE) const; 90699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Clearerr(CheckerContext &C, const CallExpr *CE) const; 91699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Feof(CheckerContext &C, const CallExpr *CE) const; 92699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Ferror(CheckerContext &C, const CallExpr *CE) const; 93699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fileno(CheckerContext &C, const CallExpr *CE) const; 94699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis 95699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void OpenFileAux(CheckerContext &C, const CallExpr *CE) const; 96c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 978bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckNullStream(SVal SV, ProgramStateRef state, 98699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const; 998bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckDoubleClose(const CallExpr *CE, ProgramStateRef state, 100699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const; 101c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu}; 102c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 10323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} // end anonymous namespace 104c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 105466224fd068a0a0084968a7f521a690a51c3b226Jordan RoseREGISTER_MAP_WITH_PROGRAMSTATE(StreamMap, SymbolRef, StreamState) 106466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose 1079843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 108699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisbool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 109b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks const FunctionDecl *FD = C.getCalleeDecl(CE); 1105ef6e94b294cc47750d8ab220858a36726caba59Jordan Rose if (!FD || FD->getKind() != Decl::Function) 111c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return false; 112c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 113c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu ASTContext &Ctx = C.getASTContext(); 114c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (!II_fopen) 115c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu II_fopen = &Ctx.Idents.get("fopen"); 11647dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu if (!II_tmpfile) 11747dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu II_tmpfile = &Ctx.Idents.get("tmpfile"); 1189843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (!II_fclose) 1199843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu II_fclose = &Ctx.Idents.get("fclose"); 120c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (!II_fread) 121c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu II_fread = &Ctx.Idents.get("fread"); 122c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fwrite) 123c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fwrite = &Ctx.Idents.get("fwrite"); 12423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_fseek) 12523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_fseek = &Ctx.Idents.get("fseek"); 12623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_ftell) 12723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_ftell = &Ctx.Idents.get("ftell"); 12823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_rewind) 12923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_rewind = &Ctx.Idents.get("rewind"); 130c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fgetpos) 131c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fgetpos = &Ctx.Idents.get("fgetpos"); 132c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fsetpos) 133c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fsetpos = &Ctx.Idents.get("fsetpos"); 134c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_clearerr) 135c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_clearerr = &Ctx.Idents.get("clearerr"); 136c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_feof) 137c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_feof = &Ctx.Idents.get("feof"); 138c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_ferror) 139c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_ferror = &Ctx.Idents.get("ferror"); 140c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fileno) 141c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fileno = &Ctx.Idents.get("fileno"); 14223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 143c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (FD->getIdentifier() == II_fopen) { 144c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fopen(C, CE); 145c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return true; 146c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 14747dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu if (FD->getIdentifier() == II_tmpfile) { 14847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu Tmpfile(C, CE); 14947dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu return true; 15047dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu } 1519843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (FD->getIdentifier() == II_fclose) { 1529843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu Fclose(C, CE); 1539843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu return true; 1549843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 155c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (FD->getIdentifier() == II_fread) { 156c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fread(C, CE); 157c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 158c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 159c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fwrite) { 160c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fwrite(C, CE); 161c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return true; 162c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 16323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_fseek) { 164c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fseek(C, CE); 16523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 16623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 16723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_ftell) { 168c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Ftell(C, CE); 16923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 17023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 17123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_rewind) { 17223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu Rewind(C, CE); 17323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 17423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 175c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fgetpos) { 176c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fgetpos(C, CE); 177c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 178c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 179c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fsetpos) { 180c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fsetpos(C, CE); 181c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 182c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 183c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_clearerr) { 184c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Clearerr(C, CE); 185c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 186c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 187c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_feof) { 188c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Feof(C, CE); 189c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 190c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 191c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_ferror) { 192c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Ferror(C, CE); 193c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 194c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 195c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fileno) { 196c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fileno(C, CE); 197c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 198c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 19923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 200c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return false; 201c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 202c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 203699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const { 20447dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu OpenFileAux(C, CE); 20547dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu} 20647dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 207699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const { 20847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu OpenFileAux(C, CE); 20947dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu} 21047dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 211699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { 2128bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 213c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 2143133f79cf451e6302dd05262b4bb53a3e4fd6300Ted Kremenek const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); 2156bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines DefinedSVal RetVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, 2166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines C.blockCount()) 2175251abea41b446c26e3239c8dd6c7edea6fc335dDavid Blaikie .castAs<DefinedSVal>(); 2185eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, C.getLocationContext(), RetVal); 21947dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 220c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 221c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu // Bifurcate the state into two: one with a valid FILE* pointer, the other 222c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu // with a NULL. 2238bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal); 22547dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 2268046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek if (SymbolRef Sym = RetVal.getAsSymbol()) { 2278046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek // if RetVal is not NULL, set the symbol's state to Opened. 2288046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNotNull = 229466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose stateNotNull->set<StreamMap>(Sym,StreamState::getOpened(CE)); 2308046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNull = 231466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose stateNull->set<StreamMap>(Sym, StreamState::getOpenFailed(CE)); 2328046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek 2330bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateNotNull); 2340bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateNull); 2358046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek } 236c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 237c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 238699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const { 2398bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = CheckDoubleClose(CE, C.getState(), C); 2409843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (state) 2410bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 2429843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu} 2439843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 244699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const { 2458bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2465eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), 2475eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 24823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 24923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 25023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 251699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const { 2528bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2535eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), 2545eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 255c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 256c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 257c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 258699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { 2598bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2605eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!(state = CheckNullStream(state->getSVal(CE->getArg(0), 2615eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek C.getLocationContext()), state, C))) 2620c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu return; 2630c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu // Check the legality of the 'whence' argument of 'fseek'. 2645eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext()); 265dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<nonloc::ConcreteInt> CI = Whence.getAs<nonloc::ConcreteInt>(); 26602b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek 2670c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu if (!CI) 26802b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek return; 2690c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu 2700c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu int64_t x = CI->getValue().getSExtValue(); 27102b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek if (x >= 0 && x <= 2) 27223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 2730c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu 2740bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks if (ExplodedNode *N = C.addTransition(state)) { 27502b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek if (!BT_illegalwhence) 276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_illegalwhence.reset( 277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new BuiltinBug(this, "Illegal whence argument", 278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "The whence argument to fseek() should be " 279651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "SEEK_SET, SEEK_END, or SEEK_CUR.")); 28002b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek BugReport *R = new BugReport(*BT_illegalwhence, 28102b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek BT_illegalwhence->getDescription(), N); 282785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(R); 28302b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek } 28423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 28523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 286699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const { 2878bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2885eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 2895eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 29023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 29123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 29223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 293699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const { 2948bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2955eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 2965eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 29723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 29823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 299c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 300699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const { 3018bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3025eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 304c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 305c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 306c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 307699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const { 3088bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3095eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3105eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 311c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 312c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 313c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 314699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const { 3158bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3165eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3175eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 318c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 319c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 320c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 321699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const { 3228bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3235eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3245eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 325c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 326c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 327c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 328699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const { 3298bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3305eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3315eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 332c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 333c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 334c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 335699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const { 3368bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3375eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3385eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 339c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 340c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 341c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 3428bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state, 343699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 344dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie Optional<DefinedSVal> DV = SV.getAs<DefinedSVal>(); 34523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!DV) 3466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 347b3f403112d40bc0a6ec240ae1feb536cc6892d47Zhongxing Xu 34823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 3498bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); 351b3f403112d40bc0a6ec240ae1feb536cc6892d47Zhongxing Xu 35223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!stateNotNull && stateNull) { 353d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateSink(stateNull)) { 35423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!BT_nullfp) 355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_nullfp.reset(new BuiltinBug(this, "NULL stream pointer", 356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Stream pointer might be NULL.")); 35723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N); 358785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(R); 359c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 3606bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 361c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 362ab42130a229ea5ee80d96cfc33799d558d79be17Zhongxing Xu return stateNotNull; 363c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 3649843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3658bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE, 3668bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 367699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 3685eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SymbolRef Sym = 3695eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol(); 3708046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek if (!Sym) 3718046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek return state; 3729843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 373466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose const StreamState *SS = state->get<StreamMap>(Sym); 3741c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu 3751c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu // If the file stream is not tracked, return. 3761c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu if (!SS) 3771c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu return state; 3789843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3799843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Check: Double close a File Descriptor could cause undefined behaviour. 3809843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Conforming to man-pages 3819843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (SS->isClosed()) { 382d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 3839843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (N) { 3849843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (!BT_doubleclose) 385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_doubleclose.reset(new BuiltinBug( 386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines this, "Double fclose", "Try to close a file Descriptor already" 387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines " closed. Cause undefined behaviour.")); 3889843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu BugReport *R = new BugReport(*BT_doubleclose, 389a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BT_doubleclose->getDescription(), N); 390785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(R); 3919843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 3926bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 3939843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 3949843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3959843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Close the File Descriptor. 396466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose return state->set<StreamMap>(Sym, StreamState::getClosed(CE)); 3979843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu} 398766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 399699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper, 400699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 4015ac1df3e15f91ed663826faec7efe2462c18d98cAnna Zaks // TODO: Clean up the state. 402766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), 403a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman E = SymReaper.dead_end(); I != E; ++I) { 404766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu SymbolRef Sym = *I; 4058bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 406466224fd068a0a0084968a7f521a690a51c3b226Jordan Rose const StreamState *SS = state->get<StreamMap>(Sym); 407766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (!SS) 4080621c45dcd4c5f43df0de5a2febae525d3287b74Anna Zaks continue; 409766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 410766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (SS->isOpened()) { 411d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 412766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (N) { 413a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman if (!BT_ResourceLeak) 414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BT_ResourceLeak.reset(new BuiltinBug( 415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines this, "Resource Leak", 416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "Opened File never closed. Potential Resource leak.")); 417a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BugReport *R = new BugReport(*BT_ResourceLeak, 418a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BT_ResourceLeak->getDescription(), N); 419785950e59424dca7ce0081bebf13c0acd2c4fff6Jordan Rose C.emitReport(R); 420766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 421766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 422766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 423766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu} 424766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 425699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid ento::registerStreamChecker(CheckerManager &mgr) { 426699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis mgr.registerChecker<StreamChecker>(); 427699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis} 428