1*0b57cec5SDimitry Andric //=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This files defines FixedAddressChecker, a builtin checker that checks for
10*0b57cec5SDimitry Andric // assignment of a fixed address to a pointer.
11*0b57cec5SDimitry Andric // This check corresponds to CWE-587.
12*0b57cec5SDimitry Andric //
13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
16*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
18*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric using namespace clang;
22*0b57cec5SDimitry Andric using namespace ento;
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric namespace {
25*0b57cec5SDimitry Andric class FixedAddressChecker
26*0b57cec5SDimitry Andric   : public Checker< check::PreStmt<BinaryOperator> > {
27*0b57cec5SDimitry Andric   mutable std::unique_ptr<BuiltinBug> BT;
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric public:
30*0b57cec5SDimitry Andric   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
31*0b57cec5SDimitry Andric };
32*0b57cec5SDimitry Andric }
33*0b57cec5SDimitry Andric 
checkPreStmt(const BinaryOperator * B,CheckerContext & C) const34*0b57cec5SDimitry Andric void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
35*0b57cec5SDimitry Andric                                        CheckerContext &C) const {
36*0b57cec5SDimitry Andric   // Using a fixed address is not portable because that address will probably
37*0b57cec5SDimitry Andric   // not be valid in all environments or platforms.
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   if (B->getOpcode() != BO_Assign)
40*0b57cec5SDimitry Andric     return;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric   QualType T = B->getType();
43*0b57cec5SDimitry Andric   if (!T->isPointerType())
44*0b57cec5SDimitry Andric     return;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   SVal RV = C.getSVal(B->getRHS());
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   if (!RV.isConstant() || RV.isZeroConstant())
49*0b57cec5SDimitry Andric     return;
50*0b57cec5SDimitry Andric 
51*0b57cec5SDimitry Andric   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
52*0b57cec5SDimitry Andric     if (!BT)
53*0b57cec5SDimitry Andric       BT.reset(
54*0b57cec5SDimitry Andric           new BuiltinBug(this, "Use fixed address",
55*0b57cec5SDimitry Andric                          "Using a fixed address is not portable because that "
56*0b57cec5SDimitry Andric                          "address will probably not be valid in all "
57*0b57cec5SDimitry Andric                          "environments or platforms."));
58*0b57cec5SDimitry Andric     auto R =
59*0b57cec5SDimitry Andric         std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
60*0b57cec5SDimitry Andric     R->addRange(B->getRHS()->getSourceRange());
61*0b57cec5SDimitry Andric     C.emitReport(std::move(R));
62*0b57cec5SDimitry Andric   }
63*0b57cec5SDimitry Andric }
64*0b57cec5SDimitry Andric 
registerFixedAddressChecker(CheckerManager & mgr)65*0b57cec5SDimitry Andric void ento::registerFixedAddressChecker(CheckerManager &mgr) {
66*0b57cec5SDimitry Andric   mgr.registerChecker<FixedAddressChecker>();
67*0b57cec5SDimitry Andric }
68*0b57cec5SDimitry Andric 
shouldRegisterFixedAddressChecker(const CheckerManager & mgr)69*0b57cec5SDimitry Andric bool ento::shouldRegisterFixedAddressChecker(const CheckerManager &mgr) {
70*0b57cec5SDimitry Andric   return true;
71 }
72