blob: a92d409703a356515164bf10abc3531b0515d53d [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> {
Jordy Rosed325ffb2010-07-08 23:57:29 +000024 BugType *BT_Null, *BT_Bounds, *BT_Overlap;
Jordy Roseccbf7ee2010-07-06 23:11:01 +000025public:
26 CStringChecker()
Jordy Rosed325ffb2010-07-08 23:57:29 +000027 : BT_Null(0), BT_Bounds(0), BT_Overlap(0) {}
Jordy Roseccbf7ee2010-07-06 23:11:01 +000028 static void *getTag() { static int tag; return &tag; }
29
30 bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
31
Jordy Rosed325ffb2010-07-08 23:57:29 +000032 typedef void (CStringChecker::*FnCheck)(CheckerContext &, const CallExpr *);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000033
Jordy Rosed325ffb2010-07-08 23:57:29 +000034 void EvalMemcpy(CheckerContext &C, const CallExpr *CE);
35 void EvalMemmove(CheckerContext &C, const CallExpr *CE);
36 void EvalBcopy(CheckerContext &C, const CallExpr *CE);
37 void EvalCopyCommon(CheckerContext &C, const GRState *state,
38 const Expr *Size, const Expr *Source, const Expr *Dest,
39 bool Restricted = false);
40
41 void EvalMemcmp(CheckerContext &C, const CallExpr *CE);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000042
43 // Utility methods
Jordy Rosed325ffb2010-07-08 23:57:29 +000044 std::pair<const GRState*, const GRState*>
45 AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
46
Jordy Rosea6b808c2010-07-07 07:48:06 +000047 const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000048 const Expr *S, SVal l);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000049 const GRState *CheckLocation(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000050 const Expr *S, SVal l);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000051 const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
52 const Expr *Size,
53 const Expr *FirstBuf,
54 const Expr *SecondBuf = NULL);
55 const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000056 const Expr *Size, const Expr *First,
57 const Expr *Second);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000058 void EmitOverlapBug(CheckerContext &C, const GRState *state,
59 const Stmt *First, const Stmt *Second);
60};
61} //end anonymous namespace
62
63void clang::RegisterCStringChecker(GRExprEngine &Eng) {
64 Eng.registerCheck(new CStringChecker());
65}
66
Jordy Rosed325ffb2010-07-08 23:57:29 +000067//===----------------------------------------------------------------------===//
68// Individual checks and utility methods.
69//===----------------------------------------------------------------------===//
70
71std::pair<const GRState*, const GRState*>
72CStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V,
73 QualType Ty) {
74 DefinedSVal *Val = dyn_cast<DefinedSVal>(&V);
75 if (!Val)
76 return std::pair<const GRState*, const GRState *>(state, state);
Jordy Rosea6b808c2010-07-07 07:48:06 +000077
78 ValueManager &ValMgr = C.getValueManager();
79 SValuator &SV = ValMgr.getSValuator();
80
Jordy Rosed325ffb2010-07-08 23:57:29 +000081 DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
82 DefinedOrUnknownSVal ValIsZero = SV.EvalEQ(state, *Val, Zero);
Jordy Rosea6b808c2010-07-07 07:48:06 +000083
Jordy Rosed325ffb2010-07-08 23:57:29 +000084 return state->Assume(ValIsZero);
85}
Jordy Rosea6b808c2010-07-07 07:48:06 +000086
Jordy Rosed325ffb2010-07-08 23:57:29 +000087const GRState *CStringChecker::CheckNonNull(CheckerContext &C,
88 const GRState *state,
89 const Expr *S, SVal l) {
90 // If a previous check has failed, propagate the failure.
91 if (!state)
92 return NULL;
93
94 const GRState *stateNull, *stateNonNull;
95 llvm::tie(stateNull, stateNonNull) = AssumeZero(C, state, l, S->getType());
96
97 if (stateNull && !stateNonNull) {
98 ExplodedNode *N = C.GenerateSink(stateNull);
Jordy Rosea6b808c2010-07-07 07:48:06 +000099 if (!N)
100 return NULL;
101
Jordy Rosed325ffb2010-07-08 23:57:29 +0000102 if (!BT_Null)
103 BT_Null = new BuiltinBug("API",
Jordy Rosea6b808c2010-07-07 07:48:06 +0000104 "Null pointer argument in call to byte string function");
105
106 // Generate a report for this bug.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000107 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000108 EnhancedBugReport *report = new EnhancedBugReport(*BT,
109 BT->getDescription(), N);
110
111 report->addRange(S->getSourceRange());
112 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
113 C.EmitReport(report);
114 return NULL;
115 }
116
117 // From here on, assume that the value is non-null.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000118 assert(stateNonNull);
119 return stateNonNull;
Jordy Rosea6b808c2010-07-07 07:48:06 +0000120}
121
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000122// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
123const GRState *CStringChecker::CheckLocation(CheckerContext &C,
124 const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000125 const Expr *S, SVal l) {
126 // If a previous check has failed, propagate the failure.
127 if (!state)
128 return NULL;
129
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000130 // Check for out of bound array element access.
131 const MemRegion *R = l.getAsRegion();
132 if (!R)
133 return state;
134
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000135 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
136 if (!ER)
137 return state;
138
139 assert(ER->getValueType(C.getASTContext()) == C.getASTContext().CharTy &&
140 "CheckLocation should only be called with char* ElementRegions");
141
142 // Get the size of the array.
143 const SubRegion *Super = cast<SubRegion>(ER->getSuperRegion());
144 ValueManager &ValMgr = C.getValueManager();
145 SVal Extent = ValMgr.convertToArrayIndex(Super->getExtent(ValMgr));
146 DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
147
148 // Get the index of the accessed element.
149 DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
150
151 const GRState *StInBound = state->AssumeInBound(Idx, Size, true);
152 const GRState *StOutBound = state->AssumeInBound(Idx, Size, false);
153 if (StOutBound && !StInBound) {
154 ExplodedNode *N = C.GenerateSink(StOutBound);
155 if (!N)
156 return NULL;
157
158 if (!BT_Bounds)
159 BT_Bounds = new BuiltinBug("Out-of-bound array access",
160 "Byte string function accesses out-of-bound array element "
161 "(buffer overflow)");
162
163 // FIXME: It would be nice to eventually make this diagnostic more clear,
164 // e.g., by referencing the original declaration or by saying *why* this
165 // reference is outside the range.
166
167 // Generate a report for this bug.
168 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
169 RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
170
171 report->addRange(S->getSourceRange());
172 C.EmitReport(report);
173 return NULL;
174 }
175
176 // Array bound check succeeded. From this point forward the array bound
177 // should always succeed.
178 return StInBound;
179}
180
181const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
182 const GRState *state,
183 const Expr *Size,
184 const Expr *FirstBuf,
185 const Expr *SecondBuf) {
Jordy Rosed325ffb2010-07-08 23:57:29 +0000186 // If a previous check has failed, propagate the failure.
187 if (!state)
188 return NULL;
189
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000190 ValueManager &VM = C.getValueManager();
191 SValuator &SV = VM.getSValuator();
192 ASTContext &Ctx = C.getASTContext();
193
194 QualType SizeTy = Ctx.getSizeType();
195 QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
196
Jordy Rosea6b808c2010-07-07 07:48:06 +0000197 // Check that the first buffer is non-null.
198 SVal BufVal = state->getSVal(FirstBuf);
199 state = CheckNonNull(C, state, FirstBuf, BufVal);
200 if (!state)
201 return NULL;
202
Jordy Rosed325ffb2010-07-08 23:57:29 +0000203 // Get the access length and make sure it is known.
204 SVal LengthVal = state->getSVal(Size);
205 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
206 if (!Length)
207 return state;
208
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000209 // Compute the offset of the last element to be accessed: size-1.
210 NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
211 NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
212 *Length, One, SizeTy));
213
Jordy Rosea6b808c2010-07-07 07:48:06 +0000214 // Check that the first buffer is sufficently long.
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000215 Loc BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, FirstBuf->getType()));
216 SVal BufEnd
217 = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
218 state = CheckLocation(C, state, FirstBuf, BufEnd);
219
220 // If the buffer isn't large enough, abort.
221 if (!state)
222 return NULL;
223
224 // If there's a second buffer, check it as well.
225 if (SecondBuf) {
226 BufVal = state->getSVal(SecondBuf);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000227 state = CheckNonNull(C, state, SecondBuf, BufVal);
228 if (!state)
229 return NULL;
230
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000231 BufStart = cast<Loc>(SV.EvalCast(BufVal, PtrTy, SecondBuf->getType()));
232 BufEnd
233 = SV.EvalBinOpLN(state, BinaryOperator::Add, BufStart, LastOffset, PtrTy);
234 state = CheckLocation(C, state, SecondBuf, BufEnd);
235 }
236
237 // Large enough or not, return this state!
238 return state;
239}
240
241const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
242 const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000243 const Expr *Size,
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000244 const Expr *First,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000245 const Expr *Second) {
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000246 // Do a simple check for overlap: if the two arguments are from the same
247 // buffer, see if the end of the first is greater than the start of the second
248 // or vice versa.
249
Jordy Rosed325ffb2010-07-08 23:57:29 +0000250 // If a previous check has failed, propagate the failure.
251 if (!state)
252 return NULL;
253
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000254 ValueManager &VM = state->getStateManager().getValueManager();
255 SValuator &SV = VM.getSValuator();
256 ASTContext &Ctx = VM.getContext();
257 const GRState *stateTrue, *stateFalse;
258
259 // Get the buffer values and make sure they're known locations.
260 SVal FirstVal = state->getSVal(First);
261 SVal SecondVal = state->getSVal(Second);
262
263 Loc *FirstLoc = dyn_cast<Loc>(&FirstVal);
264 if (!FirstLoc)
265 return state;
266
267 Loc *SecondLoc = dyn_cast<Loc>(&SecondVal);
268 if (!SecondLoc)
269 return state;
270
271 // Are the two values the same?
272 DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc);
273 llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
274
275 if (stateTrue && !stateFalse) {
276 // If the values are known to be equal, that's automatically an overlap.
277 EmitOverlapBug(C, stateTrue, First, Second);
278 return NULL;
279 }
280
281 // Assume the two expressions are not equal.
282 assert(stateFalse);
283 state = stateFalse;
284
285 // Which value comes first?
286 QualType CmpTy = Ctx.IntTy;
287 SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
288 *FirstLoc, *SecondLoc, CmpTy);
289 DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
290 if (!ReverseTest)
291 return state;
292
293 llvm::tie(stateTrue, stateFalse) = state->Assume(*ReverseTest);
294
295 if (stateTrue) {
296 if (stateFalse) {
297 // If we don't know which one comes first, we can't perform this test.
298 return state;
299 } else {
300 // Switch the values so that FirstVal is before SecondVal.
301 Loc *tmpLoc = FirstLoc;
302 FirstLoc = SecondLoc;
303 SecondLoc = tmpLoc;
304
305 // Switch the Exprs as well, so that they still correspond.
306 const Expr *tmpExpr = First;
307 First = Second;
308 Second = tmpExpr;
309 }
310 }
311
312 // Get the length, and make sure it too is known.
313 SVal LengthVal = state->getSVal(Size);
314 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
315 if (!Length)
316 return state;
317
318 // Convert the first buffer's start address to char*.
319 // Bail out if the cast fails.
320 QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
321 SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType());
322 Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
323 if (!FirstStartLoc)
324 return state;
325
326 // Compute the end of the first buffer. Bail out if THAT fails.
327 SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
328 *FirstStartLoc, *Length, CharPtrTy);
329 Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
330 if (!FirstEndLoc)
331 return state;
332
333 // Is the end of the first buffer past the start of the second buffer?
334 SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
335 *FirstEndLoc, *SecondLoc, CmpTy);
336 DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
337 if (!OverlapTest)
338 return state;
339
340 llvm::tie(stateTrue, stateFalse) = state->Assume(*OverlapTest);
341
342 if (stateTrue && !stateFalse) {
343 // Overlap!
344 EmitOverlapBug(C, stateTrue, First, Second);
345 return NULL;
346 }
347
348 // Assume the two expressions don't overlap.
349 assert(stateFalse);
350 return stateFalse;
351}
352
353void CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
354 const Stmt *First, const Stmt *Second) {
355 ExplodedNode *N = C.GenerateSink(state);
356 if (!N)
357 return;
358
359 if (!BT_Overlap)
360 BT_Overlap = new BugType("Unix API", "Improper arguments");
361
362 // Generate a report for this bug.
363 RangedBugReport *report =
364 new RangedBugReport(*BT_Overlap,
365 "Arguments must not be overlapping buffers", N);
366 report->addRange(First->getSourceRange());
367 report->addRange(Second->getSourceRange());
368
369 C.EmitReport(report);
370}
371
Jordy Rosed325ffb2010-07-08 23:57:29 +0000372//===----------------------------------------------------------------------===//
373// Evaluation of individual function calls.
374//===----------------------------------------------------------------------===//
375
376void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
377 const Expr *Size, const Expr *Dest,
378 const Expr *Source, bool Restricted) {
379 // See if the size argument is zero.
380 SVal SizeVal = state->getSVal(Size);
381 QualType SizeTy = Size->getType();
382
383 const GRState *StZeroSize, *StNonZeroSize;
384 llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
385
386 // If the size is zero, there won't be any actual memory access.
387 if (StZeroSize)
388 C.addTransition(StZeroSize);
389
390 // If the size can be nonzero, we have to check the other arguments.
391 if (StNonZeroSize) {
392 state = StNonZeroSize;
393 state = CheckBufferAccess(C, state, Size, Dest, Source);
394 if (Restricted)
395 state = CheckOverlap(C, state, Size, Dest, Source);
396 if (state)
397 C.addTransition(state);
398 }
399}
400
401
402void CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) {
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000403 // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000404 // The return value is the address of the destination buffer.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000405 const Expr *Dest = CE->getArg(0);
406 const GRState *state = C.getState();
407 state = state->BindExpr(CE, state->getSVal(Dest));
408 EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000409}
410
Jordy Rosed325ffb2010-07-08 23:57:29 +0000411void CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) {
412 // void *memmove(void *dst, const void *src, size_t n);
413 // The return value is the address of the destination buffer.
414 const Expr *Dest = CE->getArg(0);
415 const GRState *state = C.getState();
416 state = state->BindExpr(CE, state->getSVal(Dest));
417 EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
418}
419
420void CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) {
421 // void bcopy(const void *src, void *dst, size_t n);
422 EvalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
423}
424
425void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000426 // int memcmp(const void *s1, const void *s2, size_t n);
427 const Expr *Left = CE->getArg(0);
428 const Expr *Right = CE->getArg(1);
429 const Expr *Size = CE->getArg(2);
430
431 const GRState *state = C.getState();
432 ValueManager &ValMgr = C.getValueManager();
433 SValuator &SV = ValMgr.getSValuator();
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000434
Jordy Rosed325ffb2010-07-08 23:57:29 +0000435 // See if the size argument is zero.
436 SVal SizeVal = state->getSVal(Size);
437 QualType SizeTy = Size->getType();
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000438
Jordy Rosed325ffb2010-07-08 23:57:29 +0000439 const GRState *StZeroSize, *StNonZeroSize;
440 llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000441
Jordy Rosed325ffb2010-07-08 23:57:29 +0000442 // If the size can be zero, the result will be 0 in that case, and we don't
443 // have to check either of the buffers.
444 if (StZeroSize) {
445 state = StZeroSize;
446 state = state->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
447 C.addTransition(state);
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000448 }
449
Jordy Rosed325ffb2010-07-08 23:57:29 +0000450 // If the size can be nonzero, we have to check the other arguments.
451 if (StNonZeroSize) {
452 state = StNonZeroSize;
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000453
Jordy Rosed325ffb2010-07-08 23:57:29 +0000454 // If we know the two buffers are the same, we know the result is 0.
455 // First, get the two buffers' addresses. Another checker will have already
456 // made sure they're not undefined.
457 DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
458 DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000459
Jordy Rosed325ffb2010-07-08 23:57:29 +0000460 // See if they are the same.
461 DefinedOrUnknownSVal SameBuf = SV.EvalEQ(state, LV, RV);
462 const GRState *StSameBuf, *StNotSameBuf;
463 llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf);
464
465 // If the two arguments might be the same buffer, we know the result is zero,
466 // and we only need to check one size.
467 if (StSameBuf) {
468 state = StSameBuf;
469 state = CheckBufferAccess(C, state, Size, Left);
470 if (state) {
471 state = StSameBuf->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
472 C.addTransition(state);
473 }
474 }
475
476 // If the two arguments might be different buffers, we have to check the
477 // size of both of them.
478 if (StNotSameBuf) {
479 state = StNotSameBuf;
480 state = CheckBufferAccess(C, state, Size, Left, Right);
481 if (state) {
482 // The return value is the comparison result, which we don't know.
483 unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
484 SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
485 state = state->BindExpr(CE, CmpV);
486 C.addTransition(state);
487 }
488 }
489 }
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000490}
491
Jordy Rosed325ffb2010-07-08 23:57:29 +0000492//===----------------------------------------------------------------------===//
493// The driver method.
494//===----------------------------------------------------------------------===//
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000495
496bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
497 // Get the callee. All the functions we care about are C functions
498 // with simple identifiers.
499 const GRState *state = C.getState();
500 const Expr *Callee = CE->getCallee();
501 const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
502
503 if (!FD)
504 return false;
505
506 // Get the name of the callee. If it's a builtin, strip off the prefix.
507 llvm::StringRef Name = FD->getName();
508 if (Name.startswith("__builtin_"))
509 Name = Name.substr(10);
510
511 FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name)
Jordy Rosea6b808c2010-07-07 07:48:06 +0000512 .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000513 .Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
Jordy Rosea6b808c2010-07-07 07:48:06 +0000514 .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000515 .Case("bcopy", &CStringChecker::EvalBcopy)
516 .Default(NULL);
517
Jordy Rosed325ffb2010-07-08 23:57:29 +0000518 // If the callee isn't a string function, let another checker handle it.
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000519 if (!EvalFunction)
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000520 return false;
521
Jordy Rosed325ffb2010-07-08 23:57:29 +0000522 // Check and evaluate the call.
523 (this->*EvalFunction)(C, CE);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000524 return true;
525}