1b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//===--- UndefinedAssignmentChecker.h ---------------------------*- C++ -*--==//
2b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//
3b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//                     The LLVM Compiler Infrastructure
4b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//
5b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek// This file is distributed under the University of Illinois Open Source
6b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek// License. See LICENSE.TXT for details.
7b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//
8b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//===----------------------------------------------------------------------===//
9b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//
10267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis// This defines UndefinedAssignmentChecker, a builtin check in ExprEngine that
11b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek// checks for assigning undefined values.
12b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//
13b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek//===----------------------------------------------------------------------===//
14b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
15267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis#include "ClangSACheckers.h"
16ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
17267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
199b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
20b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
21b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenekusing namespace clang;
229ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
23b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
24c3372e0ee8dac4fc11c771a92b05e4641bce6b32Zhongxing Xunamespace {
25ba5fb5a955c896815c439289fc51c03cf0635129Kovarththanan Rajaratnamclass UndefinedAssignmentChecker
26ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis  : public Checker<check::Bind> {
276f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith  mutable OwningPtr<BugType> BT;
28267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis
29c3372e0ee8dac4fc11c771a92b05e4641bce6b32Zhongxing Xupublic:
30390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks  void checkBind(SVal location, SVal val, const Stmt *S,
31390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks                 CheckerContext &C) const;
32c3372e0ee8dac4fc11c771a92b05e4641bce6b32Zhongxing Xu};
33c3372e0ee8dac4fc11c771a92b05e4641bce6b32Zhongxing Xu}
34c3372e0ee8dac4fc11c771a92b05e4641bce6b32Zhongxing Xu
35267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidisvoid UndefinedAssignmentChecker::checkBind(SVal location, SVal val,
36390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks                                           const Stmt *StoreE,
37267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis                                           CheckerContext &C) const {
38b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  if (!val.isUndef())
39b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek    return;
40b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
41d048c6ef5b6cfaa0cecb8cc1d4bdace32ed21d07Ted Kremenek  ExplodedNode *N = C.generateSink();
42b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
43b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  if (!N)
44b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek    return;
45b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
4612182a0344c11970f307bc79eeb102633561b680Ted Kremenek  const char *str = "Assigned value is garbage or undefined";
4712182a0344c11970f307bc79eeb102633561b680Ted Kremenek
48b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  if (!BT)
49267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis    BT.reset(new BuiltinBug(str));
50b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
51b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  // Generate a report for this bug.
5212182a0344c11970f307bc79eeb102633561b680Ted Kremenek  const Expr *ex = 0;
53b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
5479d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek  while (StoreE) {
5579d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
5612182a0344c11970f307bc79eeb102633561b680Ted Kremenek      if (B->isCompoundAssignmentOp()) {
578bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek        ProgramStateRef state = C.getState();
585eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek        if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) {
5912182a0344c11970f307bc79eeb102633561b680Ted Kremenek          str = "The left expression of the compound assignment is an "
6012182a0344c11970f307bc79eeb102633561b680Ted Kremenek                "uninitialized value. The computed value will also be garbage";
6112182a0344c11970f307bc79eeb102633561b680Ted Kremenek          ex = B->getLHS();
6212182a0344c11970f307bc79eeb102633561b680Ted Kremenek          break;
6312182a0344c11970f307bc79eeb102633561b680Ted Kremenek        }
6412182a0344c11970f307bc79eeb102633561b680Ted Kremenek      }
6550ecd1536a2b70327e9eb2c2c2a652cde3dae365Ted Kremenek
6650ecd1536a2b70327e9eb2c2c2a652cde3dae365Ted Kremenek      ex = B->getRHS();
6712182a0344c11970f307bc79eeb102633561b680Ted Kremenek      break;
6812182a0344c11970f307bc79eeb102633561b680Ted Kremenek    }
6912182a0344c11970f307bc79eeb102633561b680Ted Kremenek
7079d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
719c378f705405d37f49795d5e915989de774fe11fTed Kremenek      const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
7250ecd1536a2b70327e9eb2c2c2a652cde3dae365Ted Kremenek      ex = VD->getInit();
7350ecd1536a2b70327e9eb2c2c2a652cde3dae365Ted Kremenek    }
7412182a0344c11970f307bc79eeb102633561b680Ted Kremenek
7512182a0344c11970f307bc79eeb102633561b680Ted Kremenek    break;
76b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  }
77b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
78e172e8b9e7fc67d7d03589af7e92fe777afcf33aAnna Zaks  BugReport *R = new BugReport(*BT, str, N);
7912182a0344c11970f307bc79eeb102633561b680Ted Kremenek  if (ex) {
8012182a0344c11970f307bc79eeb102633561b680Ted Kremenek    R->addRange(ex->getSourceRange());
81a1f81bb0e55749a1414b1b5124bb83b9052ff2acJordan Rose    bugreporter::trackNullOrUndefValue(N, ex, *R);
8212182a0344c11970f307bc79eeb102633561b680Ted Kremenek  }
83b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  C.EmitReport(R);
8412182a0344c11970f307bc79eeb102633561b680Ted Kremenek}
85b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek
86267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidisvoid ento::registerUndefinedAssignmentChecker(CheckerManager &mgr) {
87267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis  mgr.registerChecker<UndefinedAssignmentChecker>();
88267aa5c93b1eecc1d6f2c65ed2ba1fe840a9d0fdArgyrios Kyrtzidis}
89