@@ -31,99 +31,12 @@ class PointerSubChecker
31
31
const llvm::StringLiteral Msg_MemRegionDifferent =
32
32
" Subtraction of two pointers that do not point into the same array "
33
33
" is undefined behavior." ;
34
- const llvm::StringLiteral Msg_LargeArrayIndex =
35
- " Using an array index greater than the array size at pointer subtraction "
36
- " is undefined behavior." ;
37
- const llvm::StringLiteral Msg_NegativeArrayIndex =
38
- " Using a negative array index at pointer subtraction "
39
- " is undefined behavior." ;
40
- const llvm::StringLiteral Msg_BadVarIndex =
41
- " Indexing the address of a variable with other than 1 at this place "
42
- " is undefined behavior." ;
43
-
44
- // / Check that an array is indexed in the allowed range that is 0 to "one
45
- // / after the end". The "array" can be address of a non-array variable.
46
- // / @param E Expression of the pointer subtraction.
47
- // / @param ElemReg An indexed region in the subtraction expression.
48
- // / @param Reg Region of the other side of the expression.
49
- bool checkArrayBounds (CheckerContext &C, const Expr *E,
50
- const ElementRegion *ElemReg,
51
- const MemRegion *Reg) const ;
52
34
53
35
public:
54
36
void checkPreStmt (const BinaryOperator *B, CheckerContext &C) const ;
55
37
};
56
38
}
57
39
58
- static bool isArrayVar (const MemRegion *R) {
59
- while (R) {
60
- if (isa<VarRegion>(R))
61
- return true ;
62
- if (const auto *ER = dyn_cast<ElementRegion>(R))
63
- R = ER->getSuperRegion ();
64
- else
65
- return false ;
66
- }
67
- return false ;
68
- }
69
-
70
- bool PointerSubChecker::checkArrayBounds (CheckerContext &C, const Expr *E,
71
- const ElementRegion *ElemReg,
72
- const MemRegion *Reg) const {
73
- if (!ElemReg)
74
- return true ;
75
-
76
- const MemRegion *SuperReg = ElemReg->getSuperRegion ();
77
- if (!isArrayVar (SuperReg))
78
- return true ;
79
-
80
- auto ReportBug = [&](const llvm::StringLiteral &Msg) {
81
- if (ExplodedNode *N = C.generateNonFatalErrorNode ()) {
82
- auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
83
- R->addRange (E->getSourceRange ());
84
- C.emitReport (std::move (R));
85
- }
86
- };
87
-
88
- ProgramStateRef State = C.getState ();
89
- SValBuilder &SVB = C.getSValBuilder ();
90
-
91
- if (SuperReg == Reg) {
92
- // Case like `(&x + 1) - &x`. Only 1 or 0 is allowed as index.
93
- if (const llvm::APSInt *I = SVB.getKnownValue (State, ElemReg->getIndex ());
94
- I && (!I->isOne () && !I->isZero ()))
95
- ReportBug (Msg_BadVarIndex);
96
- return false ;
97
- }
98
-
99
- DefinedOrUnknownSVal ElemCount =
100
- getDynamicElementCount (State, SuperReg, SVB, ElemReg->getElementType ());
101
- auto IndexTooLarge = SVB.evalBinOp (C.getState (), BO_GT, ElemReg->getIndex (),
102
- ElemCount, SVB.getConditionType ())
103
- .getAs <DefinedOrUnknownSVal>();
104
- if (IndexTooLarge) {
105
- ProgramStateRef S1, S2;
106
- std::tie (S1, S2) = C.getState ()->assume (*IndexTooLarge);
107
- if (S1 && !S2) {
108
- ReportBug (Msg_LargeArrayIndex);
109
- return false ;
110
- }
111
- }
112
- auto IndexTooSmall = SVB.evalBinOp (State, BO_LT, ElemReg->getIndex (),
113
- SVB.makeZeroVal (SVB.getArrayIndexType ()),
114
- SVB.getConditionType ())
115
- .getAs <DefinedOrUnknownSVal>();
116
- if (IndexTooSmall) {
117
- ProgramStateRef S1, S2;
118
- std::tie (S1, S2) = State->assume (*IndexTooSmall);
119
- if (S1 && !S2) {
120
- ReportBug (Msg_NegativeArrayIndex);
121
- return false ;
122
- }
123
- }
124
- return true ;
125
- }
126
-
127
40
void PointerSubChecker::checkPreStmt (const BinaryOperator *B,
128
41
CheckerContext &C) const {
129
42
// When doing pointer subtraction, if the two pointers do not point to the
@@ -151,9 +64,11 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B,
151
64
const auto *ElemLR = dyn_cast<ElementRegion>(LR);
152
65
const auto *ElemRR = dyn_cast<ElementRegion>(RR);
153
66
154
- if (!checkArrayBounds (C, B->getLHS (), ElemLR, RR))
67
+ // Allow cases like "(&x + 1) - &x".
68
+ if (ElemLR && ElemLR->getSuperRegion () == RR)
155
69
return ;
156
- if (!checkArrayBounds (C, B->getRHS (), ElemRR, LR))
70
+ // Allow cases like "&x - (&x + 1)".
71
+ if (ElemRR && ElemRR->getSuperRegion () == LR)
157
72
return ;
158
73
159
74
const ValueDecl *DiffDeclL = nullptr ;
0 commit comments