1 //=== PointerSubChecker.cpp - Pointer subtraction checker ------*- C++ -*--===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This files defines PointerSubChecker, a builtin checker that checks for
10 // pointer subtractions on two pointers pointing to different memory chunks.
11 // This check corresponds to CWE-469.
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
16 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
17 #include "clang/StaticAnalyzer/Core/Checker.h"
18 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
20 #include "llvm/ADT/StringRef.h"
22 using namespace clang
;
26 class PointerSubChecker
27 : public Checker
< check::PreStmt
<BinaryOperator
> > {
28 mutable std::unique_ptr
<BugType
> BT
;
31 void checkPreStmt(const BinaryOperator
*B
, CheckerContext
&C
) const;
35 void PointerSubChecker::checkPreStmt(const BinaryOperator
*B
,
36 CheckerContext
&C
) const {
37 // When doing pointer subtraction, if the two pointers do not point to the
38 // same memory chunk, emit a warning.
39 if (B
->getOpcode() != BO_Sub
)
42 SVal LV
= C
.getSVal(B
->getLHS());
43 SVal RV
= C
.getSVal(B
->getRHS());
45 const MemRegion
*LR
= LV
.getAsRegion();
46 const MemRegion
*RR
= RV
.getAsRegion();
51 const MemRegion
*BaseLR
= LR
->getBaseRegion();
52 const MemRegion
*BaseRR
= RR
->getBaseRegion();
57 // Allow arithmetic on different symbolic regions.
58 if (isa
<SymbolicRegion
>(BaseLR
) || isa
<SymbolicRegion
>(BaseRR
))
61 if (ExplodedNode
*N
= C
.generateNonFatalErrorNode()) {
63 BT
.reset(new BugType(this, "Pointer subtraction"));
64 constexpr llvm::StringLiteral Msg
=
65 "Subtraction of two pointers that do not point to the same memory "
66 "chunk may cause incorrect result.";
67 auto R
= std::make_unique
<PathSensitiveBugReport
>(*BT
, Msg
, N
);
68 R
->addRange(B
->getSourceRange());
69 C
.emitReport(std::move(R
));
73 void ento::registerPointerSubChecker(CheckerManager
&mgr
) {
74 mgr
.registerChecker
<PointerSubChecker
>();
77 bool ento::shouldRegisterPointerSubChecker(const CheckerManager
&mgr
) {