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