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};
33
34class CheckResult;
35
36/// Checks the validity of accessing a memory region with extent \p Extent at
37/// offset \p Offset. The \p Flags influence the semantics of the check.
39 std::optional<NonLoc> Extent, CheckFlags Flags);
40
41class CheckResult {
42public:
43 /// When true, the bounds check noticed that the value of an unsigned
44 /// expression is constrained to negative values (because the analyzer
45 /// skipped the modeling of a cast expression). This execution path must be
46 /// discarded because it does not represent a real possibility.
47 /// FIXME: This hack is currently needed to filter out many ugly false
48 /// positives; but it should be removed when we fix cast modeling.
49 bool isCorruptedState() const { return IsCorruptedState; }
50
51 /// When true, the checked offset may be in bounds.
52 bool mayBeInBounds() const { return static_cast<bool>(InBoundsState); }
53
54 /// When true, the checked offset may be negative.
55 bool mayUnderflow() const { return MayUnderflow; }
56 /// When true, the checked offset may be >= the extent of the region.
57 bool mayOverflow() const { return ExtentIfMayOverflow.has_value(); }
58 /// When true, the checked offset may be out of bounds.
59 bool mayBeInvalid() const { return MayUnderflow || ExtentIfMayOverflow; }
60
61 /// Returns the offset of the accessed location from the beginning of the
62 /// accessd region.
63 NonLoc getOffset() const { return Offset; }
64
65 /// Returns the extent of the accessed region if it is relevant (because the
66 /// offset may overflow it), otherwise returns std::nullopt.
67 std::optional<NonLoc> getExtentIfMayOverflow() const {
68 return ExtentIfMayOverflow;
69 }
70
71 /// Returns the program state that should be used for continuing the analysis
72 /// after this bounds check. This returns null if mayBeInBounds() is false, in
73 /// that case the state before the check should be used in the error node.
74 ProgramStateRef getInBoundsState() const { return InBoundsState; }
75
76 friend CheckResult checkBounds(ProgramStateRef State, SValBuilder &SVB,
77 NonLoc Offset, std::optional<NonLoc> Extent,
78 CheckFlags Flags);
79
80private:
81 // Offset of the accessed location, measured from the start of the region.
82 // TODO: As of now, the offset and the extent are always measured in bytes,
83 // but we will probably need to allow other size units in the future.
84 const NonLoc Offset;
85
86 explicit CheckResult(NonLoc Offs) : Offset(Offs) {}
87
88 bool IsCorruptedState = false;
89 bool MayUnderflow = false;
90 std::optional<NonLoc> ExtentIfMayOverflow = std::nullopt;
91 ProgramStateRef InBoundsState = nullptr;
92};
93
94// Evaluate the comparison Value < Threshold with the help of the custom
95// simplification algorithm. Return a pair of states, where the first one
96// corresponds to "value below threshold" and the second corresponds to "value
97// at or above threshold". Returns {nullptr, nullptr} in the case when the
98// evaluation fails.
99// If the optional argument CheckEquality is true, then use BO_EQ instead of
100// the default BO_LT after consistently applying the same simplification steps.
101std::pair<ProgramStateRef, ProgramStateRef>
103 NonLoc Threshold, bool CheckEquality = false);
104} // namespace clang::ento::bounds
105
106#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),...
std::pair< ProgramStateRef, ProgramStateRef > compareValueToThreshold(ProgramStateRef State, SValBuilder &SVB, NonLoc Value, NonLoc Threshold, bool CheckEquality=false)
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