1b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//=== FixedAddressChecker.cpp - Fixed address usage checker ----*- C++ -*--===//
2b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//
3b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//                     The LLVM Compiler Infrastructure
4b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//
5b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu// This file is distributed under the University of Illinois Open Source
6b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu// License. See LICENSE.TXT for details.
7b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//
8b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//===----------------------------------------------------------------------===//
9b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//
10b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu// This files defines FixedAddressChecker, a builtin checker that checks for
11b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu// assignment of a fixed address to a pointer.
12b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu// This check corresponds to CWE-587.
13b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//
14b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu//===----------------------------------------------------------------------===//
15b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
1623ade507cecd24b03f5e4b5ebaea48eb38060262Argyrios Kyrtzidis#include "ClangSACheckers.h"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/Checker.h"
19695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
20983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
21b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
22b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xuusing namespace clang;
239ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento;
24b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
25b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xunamespace {
2687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarclass FixedAddressChecker
27ec8605f1d7ec846dbf51047bfd5c56d32d1ff91cArgyrios Kyrtzidis  : public Checker< check::PreStmt<BinaryOperator> > {
28651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  mutable std::unique_ptr<BuiltinBug> BT;
29983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis
30b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xupublic:
31983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  void checkPreStmt(const BinaryOperator *B, CheckerContext &C) const;
32b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu};
33b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu}
34b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
35983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidisvoid FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
36983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis                                       CheckerContext &C) const {
37b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  // Using a fixed address is not portable because that address will probably
38b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  // not be valid in all environments or platforms.
39b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
402de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall  if (B->getOpcode() != BO_Assign)
41b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu    return;
42b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
43b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  QualType T = B->getType();
44b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  if (!T->isPointerType())
45b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu    return;
46b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
478bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek  ProgramStateRef state = C.getState();
485eca482fe895ea57bc82410222e6426c09e63284Ted Kremenek  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());
49b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
50b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  if (!RV.isConstant() || RV.isZeroConstant())
51b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu    return;
52b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
5387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
54b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu    if (!BT)
55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      BT.reset(
56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          new BuiltinBug(this, "Use fixed address",
57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "Using a fixed address is not portable because that "
58651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "address will probably not be valid in all "
59651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "environments or platforms."));
6087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
61b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu    R->addRange(B->getRHS()->getSourceRange());
6287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar    C.emitReport(std::move(R));
63b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu  }
64b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu}
65b10a7c235f82c6eb074be097c9ae7ee51fccc9c6Zhongxing Xu
66695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidisvoid ento::registerFixedAddressChecker(CheckerManager &mgr) {
67983326f32c746f5e47161a73758e4d363263dd2cArgyrios Kyrtzidis  mgr.registerChecker<FixedAddressChecker>();
68695fb502825a53ccd178ec1c85c77929d88acb71Argyrios Kyrtzidis}
69