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