1218887Sdim//=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim// This files defines FixedAddressChecker, a builtin checker that checks for
11218887Sdim// assignment of a fixed address to a pointer.
12218887Sdim// This check corresponds to CWE-587.
13218887Sdim//
14218887Sdim//===----------------------------------------------------------------------===//
15218887Sdim
16218887Sdim#include "ClangSACheckers.h"
17252723Sdim#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18221345Sdim#include "clang/StaticAnalyzer/Core/Checker.h"
19218887Sdim#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20219077Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21218887Sdim
22218887Sdimusing namespace clang;
23218887Sdimusing namespace ento;
24218887Sdim
25218887Sdimnamespace {
26218887Sdimclass FixedAddressChecker
27221345Sdim  : public Checker< check::PreStmt<BinaryOperator> > {
28235633Sdim  mutable OwningPtr<BuiltinBug> BT;
29219077Sdim
30218887Sdimpublic:
31219077Sdim  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
32218887Sdim};
33218887Sdim}
34218887Sdim
35219077Sdimvoid FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
36219077Sdim                                       CheckerContext &C) const {
37218887Sdim  // Using a fixed address is not portable because that address will probably
38218887Sdim  // not be valid in all environments or platforms.
39218887Sdim
40218887Sdim  if (B->getOpcode() != BO_Assign)
41218887Sdim    return;
42218887Sdim
43218887Sdim  QualType T = B->getType();
44218887Sdim  if (!T->isPointerType())
45218887Sdim    return;
46218887Sdim
47235633Sdim  ProgramStateRef state = C.getState();
48235633Sdim  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
49218887Sdim
50218887Sdim  if (!RV.isConstant() || RV.isZeroConstant())
51218887Sdim    return;
52218887Sdim
53235633Sdim  if (ExplodedNode *N = C.addTransition()) {
54218887Sdim    if (!BT)
55219077Sdim      BT.reset(new BuiltinBug("Use fixed address",
56218887Sdim                          "Using a fixed address is not portable because that "
57218887Sdim                          "address will probably not be valid in all "
58219077Sdim                          "environments or platforms."));
59226890Sdim    BugReport *R = new BugReport(*BT, BT->getDescription(), N);
60218887Sdim    R->addRange(B->getRHS()->getSourceRange());
61245431Sdim    C.emitReport(R);
62218887Sdim  }
63218887Sdim}
64218887Sdim
65218887Sdimvoid ento::registerFixedAddressChecker(CheckerManager &mgr) {
66219077Sdim  mgr.registerChecker<FixedAddressChecker>();
67218887Sdim}
68