10b57cec5SDimitry Andric //=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This files defines FixedAddressChecker, a builtin checker that checks for
100b57cec5SDimitry Andric // assignment of a fixed address to a pointer.
110b57cec5SDimitry Andric // This check corresponds to CWE-587.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
170b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/Checker.h"
180b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
190b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric using namespace ento;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace {
250b57cec5SDimitry Andric class FixedAddressChecker
260b57cec5SDimitry Andric   : public Checker< check::PreStmt<BinaryOperator> > {
27*de8261c4SDimitry Andric   const BugType BT{this, "Use fixed address"};
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric public:
300b57cec5SDimitry Andric   void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
310b57cec5SDimitry Andric };
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
checkPreStmt(const BinaryOperator * B,CheckerContext & C) const340b57cec5SDimitry Andric void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
350b57cec5SDimitry Andric                                        CheckerContext &C) const {
360b57cec5SDimitry Andric   // Using a fixed address is not portable because that address will probably
370b57cec5SDimitry Andric   // not be valid in all environments or platforms.
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric   if (B->getOpcode() != BO_Assign)
400b57cec5SDimitry Andric     return;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   QualType T = B->getType();
430b57cec5SDimitry Andric   if (!T->isPointerType())
440b57cec5SDimitry Andric     return;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   SVal RV = C.getSVal(B->getRHS());
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   if (!RV.isConstant() || RV.isZeroConstant())
490b57cec5SDimitry Andric     return;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
52c9157d92SDimitry Andric     // FIXME: improve grammar in the following strings:
53c9157d92SDimitry Andric     constexpr llvm::StringLiteral Msg =
54c9157d92SDimitry Andric         "Using a fixed address is not portable because that address will "
55c9157d92SDimitry Andric         "probably not be valid in all environments or platforms.";
56*de8261c4SDimitry Andric     auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
570b57cec5SDimitry Andric     R->addRange(B->getRHS()->getSourceRange());
580b57cec5SDimitry Andric     C.emitReport(std::move(R));
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
registerFixedAddressChecker(CheckerManager & mgr)620b57cec5SDimitry Andric void ento::registerFixedAddressChecker(CheckerManager &mgr) {
630b57cec5SDimitry Andric   mgr.registerChecker<FixedAddressChecker>();
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
shouldRegisterFixedAddressChecker(const CheckerManager & mgr)665ffd83dbSDimitry Andric bool ento::shouldRegisterFixedAddressChecker(const CheckerManager &mgr) {
670b57cec5SDimitry Andric   return true;
680b57cec5SDimitry Andric }
69