17330f729Sjoerg //=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===// 27330f729Sjoerg // 37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information. 57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67330f729Sjoerg // 77330f729Sjoerg //===----------------------------------------------------------------------===// 87330f729Sjoerg // 97330f729Sjoerg // This files defines FixedAddressChecker, a builtin checker that checks for 107330f729Sjoerg // assignment of a fixed address to a pointer. 117330f729Sjoerg // This check corresponds to CWE-587. 127330f729Sjoerg // 137330f729Sjoerg //===----------------------------------------------------------------------===// 147330f729Sjoerg 157330f729Sjoerg #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 167330f729Sjoerg #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 177330f729Sjoerg #include "clang/StaticAnalyzer/Core/Checker.h" 187330f729Sjoerg #include "clang/StaticAnalyzer/Core/CheckerManager.h" 197330f729Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 207330f729Sjoerg 217330f729Sjoerg using namespace clang; 227330f729Sjoerg using namespace ento; 237330f729Sjoerg 247330f729Sjoerg namespace { 257330f729Sjoerg class FixedAddressChecker 267330f729Sjoerg : public Checker< check::PreStmt<BinaryOperator> > { 277330f729Sjoerg mutable std::unique_ptr<BuiltinBug> BT; 287330f729Sjoerg 297330f729Sjoerg public: 307330f729Sjoerg void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const; 317330f729Sjoerg }; 327330f729Sjoerg } 337330f729Sjoerg checkPreStmt(const BinaryOperator * B,CheckerContext & C) const347330f729Sjoergvoid FixedAddressChecker::checkPreStmt(const BinaryOperator *B, 357330f729Sjoerg CheckerContext &C) const { 367330f729Sjoerg // Using a fixed address is not portable because that address will probably 377330f729Sjoerg // not be valid in all environments or platforms. 387330f729Sjoerg 397330f729Sjoerg if (B->getOpcode() != BO_Assign) 407330f729Sjoerg return; 417330f729Sjoerg 427330f729Sjoerg QualType T = B->getType(); 437330f729Sjoerg if (!T->isPointerType()) 447330f729Sjoerg return; 457330f729Sjoerg 467330f729Sjoerg SVal RV = C.getSVal(B->getRHS()); 477330f729Sjoerg 487330f729Sjoerg if (!RV.isConstant() || RV.isZeroConstant()) 497330f729Sjoerg return; 507330f729Sjoerg 517330f729Sjoerg if (ExplodedNode *N = C.generateNonFatalErrorNode()) { 527330f729Sjoerg if (!BT) 537330f729Sjoerg BT.reset( 547330f729Sjoerg new BuiltinBug(this, "Use fixed address", 557330f729Sjoerg "Using a fixed address is not portable because that " 567330f729Sjoerg "address will probably not be valid in all " 577330f729Sjoerg "environments or platforms.")); 587330f729Sjoerg auto R = 597330f729Sjoerg std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N); 607330f729Sjoerg R->addRange(B->getRHS()->getSourceRange()); 617330f729Sjoerg C.emitReport(std::move(R)); 627330f729Sjoerg } 637330f729Sjoerg } 647330f729Sjoerg registerFixedAddressChecker(CheckerManager & mgr)657330f729Sjoergvoid ento::registerFixedAddressChecker(CheckerManager &mgr) { 667330f729Sjoerg mgr.registerChecker<FixedAddressChecker>(); 677330f729Sjoerg } 687330f729Sjoerg shouldRegisterFixedAddressChecker(const CheckerManager & mgr)69*e038c9c4Sjoergbool ento::shouldRegisterFixedAddressChecker(const CheckerManager &mgr) { 707330f729Sjoerg return true; 717330f729Sjoerg } 72