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" 15ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h" 16695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 17699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 189b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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, 60699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis check::DeadSymbols, 61699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis check::EndPath, 62699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis check::PreStmt<ReturnStmt> > { 63699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis mutable IdentifierInfo *II_fopen, *II_tmpfile, *II_fclose, *II_fread, 64699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis *II_fwrite, 65c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu *II_fseek, *II_ftell, *II_rewind, *II_fgetpos, *II_fsetpos, 66c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu *II_clearerr, *II_feof, *II_ferror, *II_fileno; 676f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith mutable OwningPtr<BuiltinBug> BT_nullfp, BT_illegalwhence, 68699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_doubleclose, BT_ResourceLeak; 69c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 70c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xupublic: 7123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu StreamChecker() 7247dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu : II_fopen(0), II_tmpfile(0) ,II_fclose(0), II_fread(0), II_fwrite(0), 73c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fseek(0), II_ftell(0), II_rewind(0), II_fgetpos(0), II_fsetpos(0), 74699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis II_clearerr(0), II_feof(0), II_ferror(0), II_fileno(0) {} 75c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 76699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis bool evalCall(const CallExpr *CE, CheckerContext &C) const; 77699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; 78af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks void checkEndPath(CheckerContext &Ctx) const; 79699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; 80c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 81c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xuprivate: 82699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fopen(CheckerContext &C, const CallExpr *CE) const; 83699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Tmpfile(CheckerContext &C, const CallExpr *CE) const; 84699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fclose(CheckerContext &C, const CallExpr *CE) const; 85699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fread(CheckerContext &C, const CallExpr *CE) const; 86699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fwrite(CheckerContext &C, const CallExpr *CE) const; 87699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fseek(CheckerContext &C, const CallExpr *CE) const; 88699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Ftell(CheckerContext &C, const CallExpr *CE) const; 89699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Rewind(CheckerContext &C, const CallExpr *CE) const; 90699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fgetpos(CheckerContext &C, const CallExpr *CE) const; 91699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fsetpos(CheckerContext &C, const CallExpr *CE) const; 92699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Clearerr(CheckerContext &C, const CallExpr *CE) const; 93699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Feof(CheckerContext &C, const CallExpr *CE) const; 94699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Ferror(CheckerContext &C, const CallExpr *CE) const; 95699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void Fileno(CheckerContext &C, const CallExpr *CE) const; 96699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis 97699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis void OpenFileAux(CheckerContext &C, const CallExpr *CE) const; 98c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 998bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckNullStream(SVal SV, ProgramStateRef state, 100699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const; 1018bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef CheckDoubleClose(const CallExpr *CE, ProgramStateRef state, 102699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const; 103c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu}; 104c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 10523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} // end anonymous namespace 106c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 1079843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xunamespace clang { 1089ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremeneknamespace ento { 1099843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu template <> 11018c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek struct ProgramStateTrait<StreamState> 11118c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek : public ProgramStatePartialTrait<llvm::ImmutableMap<SymbolRef, StreamState> > { 112699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis static void *GDMIndex() { static int x; return &x; } 1139843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu }; 1149843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu} 1155a4f98ff943e6a501b0fe47ade007c9bbf96cb88Argyrios Kyrtzidis} 1169843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 117699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisbool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { 118b805c8ff133ef0c62df032fa711d6b13c5afd7f4Anna Zaks const FunctionDecl *FD = C.getCalleeDecl(CE); 119c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (!FD) 120c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return false; 121c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 122c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu ASTContext &Ctx = C.getASTContext(); 123c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (!II_fopen) 124c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu II_fopen = &Ctx.Idents.get("fopen"); 12547dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu if (!II_tmpfile) 12647dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu II_tmpfile = &Ctx.Idents.get("tmpfile"); 1279843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (!II_fclose) 1289843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu II_fclose = &Ctx.Idents.get("fclose"); 129c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (!II_fread) 130c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu II_fread = &Ctx.Idents.get("fread"); 131c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fwrite) 132c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fwrite = &Ctx.Idents.get("fwrite"); 13323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_fseek) 13423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_fseek = &Ctx.Idents.get("fseek"); 13523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_ftell) 13623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_ftell = &Ctx.Idents.get("ftell"); 13723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!II_rewind) 13823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu II_rewind = &Ctx.Idents.get("rewind"); 139c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fgetpos) 140c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fgetpos = &Ctx.Idents.get("fgetpos"); 141c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fsetpos) 142c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fsetpos = &Ctx.Idents.get("fsetpos"); 143c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_clearerr) 144c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_clearerr = &Ctx.Idents.get("clearerr"); 145c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_feof) 146c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_feof = &Ctx.Idents.get("feof"); 147c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_ferror) 148c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_ferror = &Ctx.Idents.get("ferror"); 149c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (!II_fileno) 150c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu II_fileno = &Ctx.Idents.get("fileno"); 15123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 152c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (FD->getIdentifier() == II_fopen) { 153c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fopen(C, CE); 154c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return true; 155c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 15647dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu if (FD->getIdentifier() == II_tmpfile) { 15747dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu Tmpfile(C, CE); 15847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu return true; 15947dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu } 1609843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (FD->getIdentifier() == II_fclose) { 1619843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu Fclose(C, CE); 1629843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu return true; 1639843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 164c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu if (FD->getIdentifier() == II_fread) { 165c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fread(C, CE); 166c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 167c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 168c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fwrite) { 169c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fwrite(C, CE); 170c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return true; 171c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 17223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_fseek) { 173c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fseek(C, CE); 17423d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 17523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 17623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_ftell) { 177c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Ftell(C, CE); 17823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 17923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 18023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (FD->getIdentifier() == II_rewind) { 18123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu Rewind(C, CE); 18223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return true; 18323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu } 184c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fgetpos) { 185c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fgetpos(C, CE); 186c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 187c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 188c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fsetpos) { 189c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fsetpos(C, CE); 190c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 191c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 192c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_clearerr) { 193c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Clearerr(C, CE); 194c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 195c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 196c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_feof) { 197c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Feof(C, CE); 198c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 199c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 200c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_ferror) { 201c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Ferror(C, CE); 202c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 203c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 204c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu if (FD->getIdentifier() == II_fileno) { 205c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu Fileno(C, CE); 206c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return true; 207c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu } 20823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 209c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu return false; 210c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 211c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 212699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fopen(CheckerContext &C, const CallExpr *CE) const { 21347dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu OpenFileAux(C, CE); 21447dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu} 21547dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 216699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Tmpfile(CheckerContext &C, const CallExpr *CE) const { 21747dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu OpenFileAux(C, CE); 21847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu} 21947dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 220699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { 2218bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2225d0ea6d62e076c776ddad028c4eb615783be1323Anna Zaks unsigned Count = C.getCurrentBlockCount(); 223c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek SValBuilder &svalBuilder = C.getSValBuilder(); 2243133f79cf451e6302dd05262b4bb53a3e4fd6300Ted Kremenek const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); 225c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek DefinedSVal RetVal = 2263133f79cf451e6302dd05262b4bb53a3e4fd6300Ted Kremenek cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, LCtx, Count)); 2275eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state = state->BindExpr(CE, C.getLocationContext(), RetVal); 22847dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 229c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 230c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu // Bifurcate the state into two: one with a valid FILE* pointer, the other 231c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu // with a NULL. 2328bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 23328f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, RetVal); 23447dc37f1efa6942366dd61c4acb0c874049dd1e0Zhongxing Xu 2358046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek if (SymbolRef Sym = RetVal.getAsSymbol()) { 2368046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek // if RetVal is not NULL, set the symbol's state to Opened. 2378046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNotNull = 2388046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNotNull->set<StreamState>(Sym,StreamState::getOpened(CE)); 2398046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNull = 2408046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek stateNull->set<StreamState>(Sym, StreamState::getOpenFailed(CE)); 2418046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek 2420bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateNotNull); 2430bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(stateNull); 2448046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek } 245c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 246c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 247699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const { 2488bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = CheckDoubleClose(CE, C.getState(), C); 2499843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (state) 2500bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 2519843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu} 2529843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 253699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const { 2548bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2555eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), 2565eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 25723d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 25823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 25923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 260699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const { 2618bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2625eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), 2635eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 264c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 265c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 266c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 267699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { 2688bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2695eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!(state = CheckNullStream(state->getSVal(CE->getArg(0), 2705eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek C.getLocationContext()), state, C))) 2710c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu return; 2720c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu // Check the legality of the 'whence' argument of 'fseek'. 2735eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext()); 2740c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence); 27502b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek 2760c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu if (!CI) 27702b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek return; 2780c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu 2790c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu int64_t x = CI->getValue().getSExtValue(); 28002b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek if (x >= 0 && x <= 2) 28123d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 2820c2e8c87f18e861cb48965784e20b9292fb70b60Zhongxing Xu 2830bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks if (ExplodedNode *N = C.addTransition(state)) { 28402b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek if (!BT_illegalwhence) 285699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_illegalwhence.reset(new BuiltinBug("Illegal whence argument", 28602b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek "The whence argument to fseek() should be " 287699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis "SEEK_SET, SEEK_END, or SEEK_CUR.")); 28802b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek BugReport *R = new BugReport(*BT_illegalwhence, 28902b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek BT_illegalwhence->getDescription(), N); 29002b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek C.EmitReport(R); 29102b49bb23273f3488a47f8abadf0ec7a98429d1fTed Kremenek } 29223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 29323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 294699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const { 2958bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 2965eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 2975eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 29823d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 29923d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 30023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu 301699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const { 3028bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3035eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3045eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 30523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu return; 30623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu} 307c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu 308699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const { 3098bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3105eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3115eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 312c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 313c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 314c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 315699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const { 3168bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3175eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3185eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 319c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 320c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 321c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 322699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const { 3238bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3245eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3255eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 326c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 327c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 328c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 329699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const { 3308bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3315eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3325eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 333c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 334c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 335c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 336699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const { 3378bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3385eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3395eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 340c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 341c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 342c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 343699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const { 3448bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 3455eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), 3465eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state, C)) 347c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu return; 348c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu} 349c7de88b6e777ad71e730efc152413ebca160a117Zhongxing Xu 3508bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef StreamChecker::CheckNullStream(SVal SV, ProgramStateRef state, 351699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 35223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu const DefinedSVal *DV = dyn_cast<DefinedSVal>(&SV); 35323d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!DV) 3542b11fb236d41ba564a8f990c1c29564d296ca20eTed Kremenek return 0; 355b3f403112d40bc0a6ec240ae1feb536cc6892d47Zhongxing Xu 35623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu ConstraintManager &CM = C.getConstraintManager(); 3578bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef stateNotNull, stateNull; 35828f47b92e760ccf641ac91cb0fe1c12d9ca89795Ted Kremenek llvm::tie(stateNotNull, stateNull) = CM.assumeDual(state, *DV); 359b3f403112d40bc0a6ec240ae1feb536cc6892d47Zhongxing Xu 36023d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!stateNotNull && stateNull) { 361d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek if (ExplodedNode *N = C.generateSink(stateNull)) { 36223d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu if (!BT_nullfp) 363699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_nullfp.reset(new BuiltinBug("NULL stream pointer", 364699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis "Stream pointer might be NULL.")); 36523d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu BugReport *R =new BugReport(*BT_nullfp, BT_nullfp->getDescription(), N); 36623d90f90413ff1efd7e4410d28ae2cab99af1fdbZhongxing Xu C.EmitReport(R); 367c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 36812d213d9c15e376e36c26555bbb426dede870554Zhongxing Xu return 0; 369c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu } 370ab42130a229ea5ee80d96cfc33799d558d79be17Zhongxing Xu return stateNotNull; 371c196095fa0b83d10b2c20fccfcb8198ee66451aaZhongxing Xu} 3729843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3738bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef StreamChecker::CheckDoubleClose(const CallExpr *CE, 3748bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state, 375699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 3765eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SymbolRef Sym = 3775eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol(); 3788046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek if (!Sym) 3798046037b8342f46197bbee79df83a54b873ae6e6Ted Kremenek return state; 3809843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3819843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu const StreamState *SS = state->get<StreamState>(Sym); 3821c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu 3831c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu // If the file stream is not tracked, return. 3841c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu if (!SS) 3851c7370f933e4f413d8cc8964ff946d4261da2e78Zhongxing Xu return state; 3869843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 3879843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Check: Double close a File Descriptor could cause undefined behaviour. 3889843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Conforming to man-pages 3899843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (SS->isClosed()) { 390d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 3919843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (N) { 3929843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu if (!BT_doubleclose) 393699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_doubleclose.reset(new BuiltinBug("Double fclose", 394a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman "Try to close a file Descriptor already" 395699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis " closed. Cause undefined behaviour.")); 3969843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu BugReport *R = new BugReport(*BT_doubleclose, 397a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BT_doubleclose->getDescription(), N); 3989843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu C.EmitReport(R); 3999843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 4009843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu return NULL; 4019843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu } 4029843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu 4039843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu // Close the File Descriptor. 4049843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu return state->set<StreamState>(Sym, StreamState::getClosed(CE)); 4059843ba9be3560f7b283a6b5a927e4620cfce897dZhongxing Xu} 406766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 407699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::checkDeadSymbols(SymbolReaper &SymReaper, 408699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis CheckerContext &C) const { 409766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), 410a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman E = SymReaper.dead_end(); I != E; ++I) { 411766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu SymbolRef Sym = *I; 4128bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 413766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu const StreamState *SS = state->get<StreamState>(Sym); 414766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (!SS) 415766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu return; 416766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 417766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (SS->isOpened()) { 418d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek ExplodedNode *N = C.generateSink(); 419766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (N) { 420a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman if (!BT_ResourceLeak) 421699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", 422699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis "Opened File never closed. Potential Resource leak.")); 423a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BugReport *R = new BugReport(*BT_ResourceLeak, 424a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BT_ResourceLeak->getDescription(), N); 425a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman C.EmitReport(R); 426766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 427766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 428766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 429766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu} 430766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 431af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaksvoid StreamChecker::checkEndPath(CheckerContext &Ctx) const { 4328bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = Ctx.getState(); 433766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu typedef llvm::ImmutableMap<SymbolRef, StreamState> SymMap; 434766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu SymMap M = state->get<StreamState>(); 435766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 436766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu for (SymMap::iterator I = M.begin(), E = M.end(); I != E; ++I) { 437766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu StreamState SS = I->second; 438766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (SS.isOpened()) { 4390bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks ExplodedNode *N = Ctx.addTransition(state); 440766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (N) { 441766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (!BT_ResourceLeak) 442699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis BT_ResourceLeak.reset(new BuiltinBug("Resource Leak", 443699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis "Opened File never closed. Potential Resource leak.")); 444766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu BugReport *R = new BugReport(*BT_ResourceLeak, 445a7e6845660f91ec611427e1db842780e1ec12bdbEli Friedman BT_ResourceLeak->getDescription(), N); 446af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks Ctx.EmitReport(R); 447766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 448766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 449766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu } 450766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu} 451766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 452699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { 453766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu const Expr *RetE = S->getRetValue(); 454766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (!RetE) 455766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu return; 456766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 4578bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef state = C.getState(); 4585eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek SymbolRef Sym = state->getSVal(RetE, C.getLocationContext()).getAsSymbol(); 459766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 460766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (!Sym) 461766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu return; 462766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 463766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu const StreamState *SS = state->get<StreamState>(Sym); 464766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if(!SS) 465766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu return; 466766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 467766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu if (SS->isOpened()) 468766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu state = state->set<StreamState>(Sym, StreamState::getEscaped(S)); 469766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu 4700bd6b110e908892d4b5c8671a9f435a1d72ad16aAnna Zaks C.addTransition(state); 471766c20130dc6b960be420483a168c82a66b5bb7bZhongxing Xu} 472699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis 473699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidisvoid ento::registerStreamChecker(CheckerManager &mgr) { 474699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis mgr.registerChecker<StreamChecker>(); 475699bbf9f3fa67ededdd762d2637d72d2a4a88b7aArgyrios Kyrtzidis} 476