ReturnUndefChecker.cpp revision ec8605f1d7ec846dbf51047bfd5c56d32d1ff91c
1cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//== ReturnUndefChecker.cpp -------------------------------------*- C++ -*--==//
2cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//
3cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//                     The LLVM Compiler Infrastructure
4cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//
5cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar// This file is distributed under the University of Illinois Open Source
6cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar// License. See LICENSE.TXT for details.
7cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//
8cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//===----------------------------------------------------------------------===//
9cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//
10cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar// This file defines ReturnUndefChecker, which is a path-sensitive
11cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar// check which looks for undefined or garbage values being returned to the
12cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar// caller.
13cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//
14cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar//===----------------------------------------------------------------------===//
15cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
16cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar#include "ClangSACheckers.h"
17cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar#include "clang/StaticAnalyzer/Core/Checker.h"
18cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar#include "clang/StaticAnalyzer/Core/CheckerManager.h"
19cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
21cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
22cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarusing namespace clang;
23cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarusing namespace ento;
24cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
25cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarnamespace {
26cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarclass ReturnUndefChecker :
27cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    public Checker< check::PreStmt<ReturnStmt> > {
28f3e397eb17327423b3f8fff5eac8547c85efddb1Rafael Espindola  mutable llvm::OwningPtr<BuiltinBug> BT;
29cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarpublic:
30cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
31cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar};
32cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar}
33cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
34cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarvoid ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS,
35cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar                                      CheckerContext &C) const {
36cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
37cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  const Expr *RetE = RS->getRetValue();
38cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  if (!RetE)
39cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    return;
40cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
41cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  if (!C.getState()->getSVal(RetE).isUndef())
42cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    return;
43cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
44cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  ExplodedNode *N = C.generateSink();
45cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
46cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  if (!N)
47cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    return;
48cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
49cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  if (!BT)
50cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    BT.reset(new BuiltinBug("Garbage return value",
51cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar                            "Undefined or garbage value returned to caller"));
52cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
53cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  EnhancedBugReport *report =
54cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar    new EnhancedBugReport(*BT, BT->getDescription(), N);
55cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
56cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  report->addRange(RetE->getSourceRange());
57cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, RetE);
58b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar
59b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar  C.EmitReport(report);
60cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar}
61cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar
62cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbarvoid ento::registerReturnUndefChecker(CheckerManager &mgr) {
63cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar  mgr.registerChecker<ReturnUndefChecker>();
64cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar}
65cb497b888aabebe13de431c8a6e7c7d31f4dea0cDaniel Dunbar