blob: cb30c1ba051abe5b997c6072b8b3bcd388a4d289 [file] [log] [blame]
Jordy Roseccbf7ee2010-07-06 23:11:01 +00001//= CStringChecker.h - Checks calls to C string functions ----------*- C++ -*-//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This defines CStringChecker, which is an assortment of checks on calls
11// to functions in <string.h>.
12//
13//===----------------------------------------------------------------------===//
14
15#include "GRExprEngineExperimentalChecks.h"
16#include "clang/Checker/BugReporter/BugType.h"
17#include "clang/Checker/PathSensitive/CheckerVisitor.h"
18#include "llvm/ADT/StringSwitch.h"
19
20using namespace clang;
21
22namespace {
23class CStringChecker : public CheckerVisitor<CStringChecker> {
24 BugType *BT_Bounds;
25 BugType *BT_Overlap;
26public:
27 CStringChecker()
28 : BT_Bounds(0), BT_Overlap(0) {}
29 static void *getTag() { static int tag; return &tag; }
30
31 bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
32
33 typedef const GRState *(CStringChecker::*FnCheck)(CheckerContext &,
34 const CallExpr *);
35
36 const GRState *EvalMemcpy(CheckerContext &C, const CallExpr *CE);
37 const GRState *EvalMemmove(CheckerContext &C, const CallExpr *CE);
38 const GRState *EvalBcopy(CheckerContext &C, const CallExpr *CE);
39
40 // Utility methods
Jordy Rosea6b808c2010-07-07 07:48:06 +000041 const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
42 const Stmt *S, SVal l);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000043 const GRState *CheckLocation(CheckerContext &C, const GRState *state,
44 const Stmt *S, SVal l);
45 const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
46 const Expr *Size,
47 const Expr *FirstBuf,
48 const Expr *SecondBuf = NULL);
49 const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
50 const Expr *First, const Expr *Second,
51 const Expr *Size);
52 void EmitOverlapBug(CheckerContext &C, const GRState *state,
53 const Stmt *First, const Stmt *Second);
54};
55} //end anonymous namespace
56
57void clang::RegisterCStringChecker(GRExprEngine &Eng) {
58 Eng.registerCheck(new CStringChecker());
59}
60
Jordy Rosea6b808c2010-07-07 07:48:06 +000061const GRState *CStringChecker::CheckNonNull(CheckerContext &C,
62 const GRState *state,
63 const Stmt *S, SVal l) {
64 // FIXME: This method just checks, of course, that the value is non-null.
65 // It should maybe be refactored and combined with AttrNonNullChecker.
66 if (l.isUnknownOrUndef())
67 return state;
68
69 ValueManager &ValMgr = C.getValueManager();
70 SValuator &SV = ValMgr.getSValuator();
71
72 Loc Null = ValMgr.makeNull();
73 DefinedOrUnknownSVal LocIsNull = SV.EvalEQ(state, cast<Loc>(l), Null);
74
75 const GRState *stateIsNull, *stateIsNonNull;
76 llvm::tie(stateIsNull, stateIsNonNull) = state->Assume(LocIsNull);
77
78 if (stateIsNull && !stateIsNonNull) {
79 ExplodedNode *N = C.GenerateSink(stateIsNull);
80 if (!N)
81 return NULL;
82
83 if (!BT_Bounds)
84 BT_Bounds = new BuiltinBug("API",
85 "Null pointer argument in call to byte string function");
86
87 // Generate a report for this bug.
88 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
89 EnhancedBugReport *report = new EnhancedBugReport(*BT,
90 BT->getDescription(), N);
91
92 report->addRange(S->getSourceRange());
93 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
94 C.EmitReport(report);
95 return NULL;
96 }
97
98 // From here on, assume that the value is non-null.
99 assert(stateIsNonNull);
100 return stateIsNonNull;
101}
102
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000103// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
104const GRState *CStringChecker::CheckLocation(CheckerContext &C,
105 const GRState *state,
106 const Stmt *S, SVal l) {
107 // Check for out of bound array element access.
108 const MemRegion *R = l.getAsRegion();
109 if (!R)
110 return state;
111
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000112 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
113 if (!ER)
114 return state;
115
116 assert(ER->getValueType(C.getASTContext()) == C.getASTContext().CharTy &&
117 "CheckLocation should only be called with char* ElementRegions");
118
119 // Get the size of the array.
120 const SubRegion *Super = cast<SubRegion>(ER->getSuperRegion());
121 ValueManager &ValMgr = C.getValueManager();
122 SVal Extent = ValMgr.convertToArrayIndex(Super->getExtent(ValMgr));
123 DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
124
125 // Get the index of the accessed element.
126 DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
127
128 const GRState *StInBound = state->AssumeInBound(Idx, Size, true);
129 const GRState *StOutBound = state->AssumeInBound(Idx, Size, false);
130 if (StOutBound && !StInBound) {
131 ExplodedNode *N = C.GenerateSink(StOutBound);
132 if (!N)
133 return NULL;
134
135 if (!BT_Bounds)
136 BT_Bounds = new BuiltinBug("Out-of-bound array access",
137 "Byte string function accesses out-of-bound array element "
138 "(buffer overflow)");
139
140 // FIXME: It would be nice to eventually make this diagnostic more clear,
141 // e.g., by referencing the original declaration or by saying *why* this
142 // reference is outside the range.
143
144 // Generate a report for this bug.
145 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
146 RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
147
148 report->addRange(S->getSourceRange());
149 C.EmitReport(report);
150 return NULL;
151 }
152
153 // Array bound check succeeded. From this point forward the array bound
154 // should always succeed.
155 return StInBound;
156}
157
158const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
159 const GRState *state,
160 const Expr *Size,
161 const Expr *FirstBuf,
162 const Expr *SecondBuf) {
163 ValueManager &VM = C.getValueManager();
164 SValuator &SV = VM.getSValuator();
165 ASTContext &Ctx = C.getASTContext();
166
167 QualType SizeTy = Ctx.getSizeType();
168 QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
169
170 // Get the access length and make sure it is known.
171 SVal LengthVal = state->getSVal(Size);
172 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
173 if (!Length)
174 return state;
175
Jordy Rosea6b808c2010-07-07 07:48:06 +0000176 // If the length is zero, it doesn't matter what the two buffers are.
177 DefinedOrUnknownSVal Zero = VM.makeZeroVal(SizeTy);
178 DefinedOrUnknownSVal LengthIsZero = SV.EvalEQ(state, *Length, Zero);
179
180 const GRState *stateZeroLength, *stateNonZeroLength;
181 llvm::tie(stateZeroLength, stateNonZeroLength) = state->Assume(LengthIsZero);
182 if (stateZeroLength && !stateNonZeroLength)
183 return stateZeroLength;
184
185 // FIXME: At this point all we know is it's *possible* for the length to be
186 // nonzero; we don't know it for sure. Unfortunately, that means the next few
187 // tests are incorrect for the edge cases in which a buffer is null or invalid
188 // but the size argument was set to zero in some way that we couldn't track.
189 // What we should really do is bifurcate the state here, but that doesn't
190 // match the way CheckBufferAccess is being used.
191
192 // From here on, we're going to pretend that even if the length is zero, the
193 // buffer access rules still apply. That means the buffer must be non-NULL,
194 // and the value at buffer[size-1] must be valid.
195
196 // Check that the first buffer is non-null.
197 SVal BufVal = state->getSVal(FirstBuf);
198 state = CheckNonNull(C, state, FirstBuf, BufVal);
199 if (!state)
200 return NULL;
201
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000202 // Compute the offset of the last element to be accessed: size-1.
203 NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
204 NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
205 *Length, One, SizeTy));
206
Jordy Rosea6b808c2010-07-07 07:48:06 +0000207 // Check that the first buffer is sufficently long.
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000208 Loc BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, FirstBuf->getType()));
209 SVal BufEnd
210 = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
211 state = CheckLocation(C, state, FirstBuf, BufEnd);
212
213 // If the buffer isn't large enough, abort.
214 if (!state)
215 return NULL;
216
217 // If there's a second buffer, check it as well.
218 if (SecondBuf) {
219 BufVal = state->getSVal(SecondBuf);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000220 state = CheckNonNull(C, state, SecondBuf, BufVal);
221 if (!state)
222 return NULL;
223
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000224 BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, SecondBuf->getType()));
225 BufEnd
226 = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
227 state = CheckLocation(C, state, SecondBuf, BufEnd);
228 }
229
230 // Large enough or not, return this state!
231 return state;
232}
233
234const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
235 const GRState *state,
236 const Expr *First,
237 const Expr *Second,
238 const Expr *Size) {
239 // Do a simple check for overlap: if the two arguments are from the same
240 // buffer, see if the end of the first is greater than the start of the second
241 // or vice versa.
242
243 ValueManager &VM = state->getStateManager().getValueManager();
244 SValuator &SV = VM.getSValuator();
245 ASTContext &Ctx = VM.getContext();
246 const GRState *stateTrue, *stateFalse;
247
248 // Get the buffer values and make sure they're known locations.
249 SVal FirstVal = state->getSVal(First);
250 SVal SecondVal = state->getSVal(Second);
251
252 Loc *FirstLoc = dyn_cast<Loc>(&FirstVal);
253 if (!FirstLoc)
254 return state;
255
256 Loc *SecondLoc = dyn_cast<Loc>(&SecondVal);
257 if (!SecondLoc)
258 return state;
259
260 // Are the two values the same?
261 DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc);
262 llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
263
264 if (stateTrue && !stateFalse) {
265 // If the values are known to be equal, that's automatically an overlap.
266 EmitOverlapBug(C, stateTrue, First, Second);
267 return NULL;
268 }
269
270 // Assume the two expressions are not equal.
271 assert(stateFalse);
272 state = stateFalse;
273
274 // Which value comes first?
275 QualType CmpTy = Ctx.IntTy;
276 SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
277 *FirstLoc, *SecondLoc, CmpTy);
278 DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
279 if (!ReverseTest)
280 return state;
281
282 llvm::tie(stateTrue, stateFalse) = state->Assume(*ReverseTest);
283
284 if (stateTrue) {
285 if (stateFalse) {
286 // If we don't know which one comes first, we can't perform this test.
287 return state;
288 } else {
289 // Switch the values so that FirstVal is before SecondVal.
290 Loc *tmpLoc = FirstLoc;
291 FirstLoc = SecondLoc;
292 SecondLoc = tmpLoc;
293
294 // Switch the Exprs as well, so that they still correspond.
295 const Expr *tmpExpr = First;
296 First = Second;
297 Second = tmpExpr;
298 }
299 }
300
301 // Get the length, and make sure it too is known.
302 SVal LengthVal = state->getSVal(Size);
303 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
304 if (!Length)
305 return state;
306
307 // Convert the first buffer's start address to char*.
308 // Bail out if the cast fails.
309 QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
310 SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType());
311 Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
312 if (!FirstStartLoc)
313 return state;
314
315 // Compute the end of the first buffer. Bail out if THAT fails.
316 SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
317 *FirstStartLoc, *Length, CharPtrTy);
318 Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
319 if (!FirstEndLoc)
320 return state;
321
322 // Is the end of the first buffer past the start of the second buffer?
323 SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
324 *FirstEndLoc, *SecondLoc, CmpTy);
325 DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
326 if (!OverlapTest)
327 return state;
328
329 llvm::tie(stateTrue, stateFalse) = state->Assume(*OverlapTest);
330
331 if (stateTrue && !stateFalse) {
332 // Overlap!
333 EmitOverlapBug(C, stateTrue, First, Second);
334 return NULL;
335 }
336
337 // Assume the two expressions don't overlap.
338 assert(stateFalse);
339 return stateFalse;
340}
341
342void CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
343 const Stmt *First, const Stmt *Second) {
344 ExplodedNode *N = C.GenerateSink(state);
345 if (!N)
346 return;
347
348 if (!BT_Overlap)
349 BT_Overlap = new BugType("Unix API", "Improper arguments");
350
351 // Generate a report for this bug.
352 RangedBugReport *report =
353 new RangedBugReport(*BT_Overlap,
354 "Arguments must not be overlapping buffers", N);
355 report->addRange(First->getSourceRange());
356 report->addRange(Second->getSourceRange());
357
358 C.EmitReport(report);
359}
360
361const GRState *
362CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) {
363 // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
364 // memcpy() is like memmove(), but with the extra requirement that the buffers
365 // not overlap.
366 const GRState *state = EvalMemmove(C, CE);
367 if (!state)
368 return NULL;
369
370 return CheckOverlap(C, state, CE->getArg(0), CE->getArg(1), CE->getArg(2));
371}
372
373const GRState *
374CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) {
375 // void *memmove(void *dst, const void *src, size_t n);
376 const Expr *Dest = CE->getArg(0);
377 const Expr *Source = CE->getArg(1);
378 const Expr *Size = CE->getArg(2);
379
380 // Check that the accesses will stay in bounds.
381 const GRState *state = C.getState();
382 state = CheckBufferAccess(C, state, Size, Dest, Source);
383 if (!state)
384 return NULL;
385
386 // The return value is the address of the destination buffer.
387 return state->BindExpr(CE, state->getSVal(Dest));
388}
389
390const GRState *
391CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) {
392 // void bcopy(const void *src, void *dst, size_t n);
393 return CheckBufferAccess(C, C.getState(),
394 CE->getArg(2), CE->getArg(0), CE->getArg(1));
395}
396
397bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
398 // Get the callee. All the functions we care about are C functions
399 // with simple identifiers.
400 const GRState *state = C.getState();
401 const Expr *Callee = CE->getCallee();
402 const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
403
404 if (!FD)
405 return false;
406
407 // Get the name of the callee. If it's a builtin, strip off the prefix.
408 llvm::StringRef Name = FD->getName();
409 if (Name.startswith("__builtin_"))
410 Name = Name.substr(10);
411
412 FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name)
Jordy Rosea6b808c2010-07-07 07:48:06 +0000413 .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
414 .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000415 .Case("bcopy", &CStringChecker::EvalBcopy)
416 .Default(NULL);
417
418 if (!EvalFunction)
419 // The callee isn't a string function. Let another checker handle it.
420 return false;
421
422 const GRState *NewState = (this->*EvalFunction)(C, CE);
423
424 if (NewState)
425 C.addTransition(NewState);
426 return true;
427}