clang 24.0.0git
BoundsChecking.h
Go to the documentation of this file.
1//===- BoundsChecking.h - Bounds checking related APIs ----------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This header declares 'checkBounds', a function that compares memory offsets
10// (that may be symbolic) and uses heuristical workarounds to provide more
11// accurate results than directly calling evalBinOp or assumeInBound.
12//
13// As of now, this logic only supports the needs of `security.ArrayBound`, but
14// in the future it will be generalized and applied in all checkers that
15// perform bounds checking (to bring them out of `alpha` stage).
16//
17// TODO: This header should be extended by other utilities (e.g. message
18// formatting tools) that are relevant for multiple bounds checking checkers.
19//
20//===----------------------------------------------------------------------===//
21
22#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_BOUNDSCHECKING_H
23#define LLVM_CLANG_STATICANALYZER_CHECKERS_BOUNDSCHECKING_H
25#include <optional>
26
28
29struct CheckFlags {
30 unsigned CheckUnderflow : 1;
32 unsigned AcceptPastTheEnd : 1;
33};
34
35class CheckResult;
36
37/// Checks the validity of accessing a memory region with extent \p Extent at
38/// offset \p Offset. The \p Flags influence the semantics of the check, in
39/// particular if `AcceptPastTheEnd` is true, then Offset == Extent is also
40/// accepted as valid.
42 std::optional<NonLoc> Extent, CheckFlags Flags);
43
44class CheckResult {
45public:
46 /// When true, the bounds check noticed that the value of an unsigned
47 /// expression is constrained to negative values (because the analyzer
48 /// skipped the modeling of a cast expression). This execution path must be
49 /// discarded because it does not represent a real possibility.
50 /// FIXME: This hack is currently needed to filter out many ugly false
51 /// positives; but it should be removed when we fix cast modeling.
52 bool isCorruptedState() const { return IsCorruptedState; }
53
54 /// When true, the checked offset may be in bounds.
55 /// As an exceptional case, this is also true for idiomatic expressions that
56 /// define a past-the-end pointer (and do not dereference it).
57 bool mayBeInBounds() const { return static_cast<bool>(InBoundsState); }
58
59 /// When true, the checked offset may be negative.
60 bool mayUnderflow() const { return MayUnderflow; }
61 /// When true, the checked offset may be >= the extent of the region.
62 /// As an exceptional case, this is also false for idiomatic expressions that
63 /// define a past-the-end pointer (and do not dereference it).
64 bool mayOverflow() const { return ExtentIfMayOverflow.has_value(); }
65 /// When true, the checked offset may be out of bounds.
66 bool mayBeInvalid() const { return MayUnderflow || ExtentIfMayOverflow; }
67
68 /// Returns the offset of the accessed location from the beginning of the
69 /// accessd region.
70 NonLoc getOffset() const { return Offset; }
71
72 /// Returns the extent of the accessed region if it is relevant (because the
73 /// offset may overflow it), otherwise returns std::nullopt.
74 std::optional<NonLoc> getExtentIfMayOverflow() const {
75 return ExtentIfMayOverflow;
76 }
77
78 /// Returns the program state that should be used for continuing the analysis
79 /// after this bounds check. This returns null if mayBeInBounds() is false, in
80 /// that case the state before the check should be used in the error node.
81 /// Note that we also have a valid state in the exception case when the
82 /// 'access' calculates the past-the-end pointer without dereferencing it.
83 ProgramStateRef getInBoundsState() const { return InBoundsState; }
84
85 friend CheckResult checkBounds(ProgramStateRef State, SValBuilder &SVB,
86 NonLoc Offset, std::optional<NonLoc> Extent,
87 CheckFlags Flags);
88
89private:
90 // Offset of the accessed location, measured from the start of the region.
91 // TODO: As of now, the offset and the extent are always measured in bytes,
92 // but we will probably need to allow other size units in the future.
93 const NonLoc Offset;
94
95 explicit CheckResult(NonLoc Offs) : Offset(Offs) {}
96
97 bool IsCorruptedState = false;
98 bool MayUnderflow = false;
99 std::optional<NonLoc> ExtentIfMayOverflow = std::nullopt;
100 ProgramStateRef InBoundsState = nullptr;
101};
102
103} // namespace clang::ento::bounds
104
105#endif // LLVM_CLANG_STATICANALYZER_CHECKERS_BOUNDSCHECKING_H
bool mayBeInBounds() const
When true, the checked offset may be in bounds.
bool mayBeInvalid() const
When true, the checked offset may be out of bounds.
bool mayUnderflow() const
When true, the checked offset may be negative.
NonLoc getOffset() const
Returns the offset of the accessed location from the beginning of the accessd region.
friend CheckResult checkBounds(ProgramStateRef State, SValBuilder &SVB, NonLoc Offset, std::optional< NonLoc > Extent, CheckFlags Flags)
Checks the validity of accessing a memory region with extent Extent at offset Offset.
ProgramStateRef getInBoundsState() const
Returns the program state that should be used for continuing the analysis after this bounds check.
bool mayOverflow() const
When true, the checked offset may be >= the extent of the region.
bool isCorruptedState() const
When true, the bounds check noticed that the value of an unsigned expression is constrained to negati...
std::optional< NonLoc > getExtentIfMayOverflow() const
Returns the extent of the accessed region if it is relevant (because the offset may overflow it),...
CheckResult checkBounds(ProgramStateRef State, SValBuilder &SVB, NonLoc Offset, std::optional< NonLoc > Extent, CheckFlags Flags)
Checks the validity of accessing a memory region with extent Extent at offset Offset.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef