blob: bb40b04bb1a0d209deb267e329cd72cd913d8f5c [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 Rose19c5dd12010-07-27 01:37:31 +000024 BugType *BT_Null, *BT_Bounds, *BT_Overlap, *BT_NotCString;
Jordy Roseccbf7ee2010-07-06 23:11:01 +000025public:
26 CStringChecker()
Jordy Rose19c5dd12010-07-27 01:37:31 +000027 : BT_Null(0), BT_Bounds(0), BT_Overlap(0), BT_NotCString(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
Jordy Rose19c5dd12010-07-27 01:37:31 +000043 void EvalStrlen(CheckerContext &C, const CallExpr *CE);
44
Jordy Roseccbf7ee2010-07-06 23:11:01 +000045 // Utility methods
Jordy Rosed325ffb2010-07-08 23:57:29 +000046 std::pair<const GRState*, const GRState*>
47 AssumeZero(CheckerContext &C, const GRState *state, SVal V, QualType Ty);
48
Jordy Rose19c5dd12010-07-27 01:37:31 +000049 SVal GetCStringLength(CheckerContext &C, const GRState *state,
50 const Expr *Ex, SVal Buf);
51
52 bool SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
53 const MemRegion *MR);
54
55 // Re-usable checks
Jordy Rosea6b808c2010-07-07 07:48:06 +000056 const GRState *CheckNonNull(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000057 const Expr *S, SVal l);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000058 const GRState *CheckLocation(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000059 const Expr *S, SVal l);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000060 const GRState *CheckBufferAccess(CheckerContext &C, const GRState *state,
61 const Expr *Size,
62 const Expr *FirstBuf,
63 const Expr *SecondBuf = NULL);
64 const GRState *CheckOverlap(CheckerContext &C, const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +000065 const Expr *Size, const Expr *First,
66 const Expr *Second);
Jordy Roseccbf7ee2010-07-06 23:11:01 +000067 void EmitOverlapBug(CheckerContext &C, const GRState *state,
68 const Stmt *First, const Stmt *Second);
69};
70} //end anonymous namespace
71
72void clang::RegisterCStringChecker(GRExprEngine &Eng) {
73 Eng.registerCheck(new CStringChecker());
74}
75
Jordy Rosed325ffb2010-07-08 23:57:29 +000076//===----------------------------------------------------------------------===//
77// Individual checks and utility methods.
78//===----------------------------------------------------------------------===//
79
80std::pair<const GRState*, const GRState*>
81CStringChecker::AssumeZero(CheckerContext &C, const GRState *state, SVal V,
82 QualType Ty) {
83 DefinedSVal *Val = dyn_cast<DefinedSVal>(&V);
84 if (!Val)
85 return std::pair<const GRState*, const GRState *>(state, state);
Jordy Rosea6b808c2010-07-07 07:48:06 +000086
87 ValueManager &ValMgr = C.getValueManager();
88 SValuator &SV = ValMgr.getSValuator();
89
Jordy Rosed325ffb2010-07-08 23:57:29 +000090 DefinedOrUnknownSVal Zero = ValMgr.makeZeroVal(Ty);
91 DefinedOrUnknownSVal ValIsZero = SV.EvalEQ(state, *Val, Zero);
Jordy Rosea6b808c2010-07-07 07:48:06 +000092
Jordy Rosed325ffb2010-07-08 23:57:29 +000093 return state->Assume(ValIsZero);
94}
Jordy Rosea6b808c2010-07-07 07:48:06 +000095
Jordy Rosed325ffb2010-07-08 23:57:29 +000096const GRState *CStringChecker::CheckNonNull(CheckerContext &C,
97 const GRState *state,
98 const Expr *S, SVal l) {
99 // If a previous check has failed, propagate the failure.
100 if (!state)
101 return NULL;
102
103 const GRState *stateNull, *stateNonNull;
104 llvm::tie(stateNull, stateNonNull) = AssumeZero(C, state, l, S->getType());
105
106 if (stateNull && !stateNonNull) {
107 ExplodedNode *N = C.GenerateSink(stateNull);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000108 if (!N)
109 return NULL;
110
Jordy Rosed325ffb2010-07-08 23:57:29 +0000111 if (!BT_Null)
112 BT_Null = new BuiltinBug("API",
Jordy Rosea6b808c2010-07-07 07:48:06 +0000113 "Null pointer argument in call to byte string function");
114
115 // Generate a report for this bug.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000116 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Null);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000117 EnhancedBugReport *report = new EnhancedBugReport(*BT,
118 BT->getDescription(), N);
119
120 report->addRange(S->getSourceRange());
121 report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, S);
122 C.EmitReport(report);
123 return NULL;
124 }
125
126 // From here on, assume that the value is non-null.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000127 assert(stateNonNull);
128 return stateNonNull;
Jordy Rosea6b808c2010-07-07 07:48:06 +0000129}
130
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000131// FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor?
132const GRState *CStringChecker::CheckLocation(CheckerContext &C,
133 const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000134 const Expr *S, SVal l) {
135 // If a previous check has failed, propagate the failure.
136 if (!state)
137 return NULL;
138
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000139 // Check for out of bound array element access.
140 const MemRegion *R = l.getAsRegion();
141 if (!R)
142 return state;
143
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000144 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
145 if (!ER)
146 return state;
147
148 assert(ER->getValueType(C.getASTContext()) == C.getASTContext().CharTy &&
149 "CheckLocation should only be called with char* ElementRegions");
150
151 // Get the size of the array.
152 const SubRegion *Super = cast<SubRegion>(ER->getSuperRegion());
153 ValueManager &ValMgr = C.getValueManager();
154 SVal Extent = ValMgr.convertToArrayIndex(Super->getExtent(ValMgr));
155 DefinedOrUnknownSVal Size = cast<DefinedOrUnknownSVal>(Extent);
156
157 // Get the index of the accessed element.
158 DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
159
160 const GRState *StInBound = state->AssumeInBound(Idx, Size, true);
161 const GRState *StOutBound = state->AssumeInBound(Idx, Size, false);
162 if (StOutBound && !StInBound) {
163 ExplodedNode *N = C.GenerateSink(StOutBound);
164 if (!N)
165 return NULL;
166
167 if (!BT_Bounds)
168 BT_Bounds = new BuiltinBug("Out-of-bound array access",
169 "Byte string function accesses out-of-bound array element "
170 "(buffer overflow)");
171
172 // FIXME: It would be nice to eventually make this diagnostic more clear,
173 // e.g., by referencing the original declaration or by saying *why* this
174 // reference is outside the range.
175
176 // Generate a report for this bug.
177 BuiltinBug *BT = static_cast<BuiltinBug*>(BT_Bounds);
178 RangedBugReport *report = new RangedBugReport(*BT, BT->getDescription(), N);
179
180 report->addRange(S->getSourceRange());
181 C.EmitReport(report);
182 return NULL;
183 }
184
185 // Array bound check succeeded. From this point forward the array bound
186 // should always succeed.
187 return StInBound;
188}
189
190const GRState *CStringChecker::CheckBufferAccess(CheckerContext &C,
191 const GRState *state,
192 const Expr *Size,
193 const Expr *FirstBuf,
194 const Expr *SecondBuf) {
Jordy Rosed325ffb2010-07-08 23:57:29 +0000195 // If a previous check has failed, propagate the failure.
196 if (!state)
197 return NULL;
198
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000199 ValueManager &VM = C.getValueManager();
200 SValuator &SV = VM.getSValuator();
201 ASTContext &Ctx = C.getASTContext();
202
203 QualType SizeTy = Ctx.getSizeType();
204 QualType PtrTy = Ctx.getPointerType(Ctx.CharTy);
205
Jordy Rosea6b808c2010-07-07 07:48:06 +0000206 // Check that the first buffer is non-null.
207 SVal BufVal = state->getSVal(FirstBuf);
208 state = CheckNonNull(C, state, FirstBuf, BufVal);
209 if (!state)
210 return NULL;
211
Jordy Rosed325ffb2010-07-08 23:57:29 +0000212 // Get the access length and make sure it is known.
213 SVal LengthVal = state->getSVal(Size);
214 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
215 if (!Length)
216 return state;
217
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000218 // Compute the offset of the last element to be accessed: size-1.
219 NonLoc One = cast<NonLoc>(VM.makeIntVal(1, SizeTy));
220 NonLoc LastOffset = cast<NonLoc>(SV.EvalBinOpNN(state, BinaryOperator::Sub,
221 *Length, One, SizeTy));
222
Jordy Rosea6b808c2010-07-07 07:48:06 +0000223 // Check that the first buffer is sufficently long.
Jordy Roseb6a40262010-08-05 23:11:30 +0000224 SVal BufStart = SV.EvalCast(BufVal, PtrTy, FirstBuf->getType());
225 if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
226 SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc,
227 LastOffset, PtrTy);
228 state = CheckLocation(C, state, FirstBuf, BufEnd);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000229
Jordy Roseb6a40262010-08-05 23:11:30 +0000230 // If the buffer isn't large enough, abort.
231 if (!state)
232 return NULL;
233 }
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000234
235 // If there's a second buffer, check it as well.
236 if (SecondBuf) {
237 BufVal = state->getSVal(SecondBuf);
Jordy Rosea6b808c2010-07-07 07:48:06 +0000238 state = CheckNonNull(C, state, SecondBuf, BufVal);
239 if (!state)
240 return NULL;
241
Jordy Roseb6a40262010-08-05 23:11:30 +0000242 BufStart = SV.EvalCast(BufVal, PtrTy, SecondBuf->getType());
243 if (Loc *BufLoc = dyn_cast<Loc>(&BufStart)) {
244 SVal BufEnd = SV.EvalBinOpLN(state, BinaryOperator::Add, *BufLoc,
245 LastOffset, PtrTy);
246 state = CheckLocation(C, state, SecondBuf, BufEnd);
247 }
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000248 }
249
250 // Large enough or not, return this state!
251 return state;
252}
253
254const GRState *CStringChecker::CheckOverlap(CheckerContext &C,
255 const GRState *state,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000256 const Expr *Size,
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000257 const Expr *First,
Jordy Rosed325ffb2010-07-08 23:57:29 +0000258 const Expr *Second) {
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000259 // Do a simple check for overlap: if the two arguments are from the same
260 // buffer, see if the end of the first is greater than the start of the second
261 // or vice versa.
262
Jordy Rosed325ffb2010-07-08 23:57:29 +0000263 // If a previous check has failed, propagate the failure.
264 if (!state)
265 return NULL;
266
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000267 ValueManager &VM = state->getStateManager().getValueManager();
268 SValuator &SV = VM.getSValuator();
269 ASTContext &Ctx = VM.getContext();
270 const GRState *stateTrue, *stateFalse;
271
272 // Get the buffer values and make sure they're known locations.
273 SVal FirstVal = state->getSVal(First);
274 SVal SecondVal = state->getSVal(Second);
275
276 Loc *FirstLoc = dyn_cast<Loc>(&FirstVal);
277 if (!FirstLoc)
278 return state;
279
280 Loc *SecondLoc = dyn_cast<Loc>(&SecondVal);
281 if (!SecondLoc)
282 return state;
283
284 // Are the two values the same?
285 DefinedOrUnknownSVal EqualTest = SV.EvalEQ(state, *FirstLoc, *SecondLoc);
286 llvm::tie(stateTrue, stateFalse) = state->Assume(EqualTest);
287
288 if (stateTrue && !stateFalse) {
289 // If the values are known to be equal, that's automatically an overlap.
290 EmitOverlapBug(C, stateTrue, First, Second);
291 return NULL;
292 }
293
294 // Assume the two expressions are not equal.
295 assert(stateFalse);
296 state = stateFalse;
297
298 // Which value comes first?
299 QualType CmpTy = Ctx.IntTy;
300 SVal Reverse = SV.EvalBinOpLL(state, BinaryOperator::GT,
301 *FirstLoc, *SecondLoc, CmpTy);
302 DefinedOrUnknownSVal *ReverseTest = dyn_cast<DefinedOrUnknownSVal>(&Reverse);
303 if (!ReverseTest)
304 return state;
305
306 llvm::tie(stateTrue, stateFalse) = state->Assume(*ReverseTest);
307
308 if (stateTrue) {
309 if (stateFalse) {
310 // If we don't know which one comes first, we can't perform this test.
311 return state;
312 } else {
313 // Switch the values so that FirstVal is before SecondVal.
314 Loc *tmpLoc = FirstLoc;
315 FirstLoc = SecondLoc;
316 SecondLoc = tmpLoc;
317
318 // Switch the Exprs as well, so that they still correspond.
319 const Expr *tmpExpr = First;
320 First = Second;
321 Second = tmpExpr;
322 }
323 }
324
325 // Get the length, and make sure it too is known.
326 SVal LengthVal = state->getSVal(Size);
327 NonLoc *Length = dyn_cast<NonLoc>(&LengthVal);
328 if (!Length)
329 return state;
330
331 // Convert the first buffer's start address to char*.
332 // Bail out if the cast fails.
333 QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy);
334 SVal FirstStart = SV.EvalCast(*FirstLoc, CharPtrTy, First->getType());
335 Loc *FirstStartLoc = dyn_cast<Loc>(&FirstStart);
336 if (!FirstStartLoc)
337 return state;
338
339 // Compute the end of the first buffer. Bail out if THAT fails.
340 SVal FirstEnd = SV.EvalBinOpLN(state, BinaryOperator::Add,
341 *FirstStartLoc, *Length, CharPtrTy);
342 Loc *FirstEndLoc = dyn_cast<Loc>(&FirstEnd);
343 if (!FirstEndLoc)
344 return state;
345
346 // Is the end of the first buffer past the start of the second buffer?
347 SVal Overlap = SV.EvalBinOpLL(state, BinaryOperator::GT,
348 *FirstEndLoc, *SecondLoc, CmpTy);
349 DefinedOrUnknownSVal *OverlapTest = dyn_cast<DefinedOrUnknownSVal>(&Overlap);
350 if (!OverlapTest)
351 return state;
352
353 llvm::tie(stateTrue, stateFalse) = state->Assume(*OverlapTest);
354
355 if (stateTrue && !stateFalse) {
356 // Overlap!
357 EmitOverlapBug(C, stateTrue, First, Second);
358 return NULL;
359 }
360
361 // Assume the two expressions don't overlap.
362 assert(stateFalse);
363 return stateFalse;
364}
365
366void CStringChecker::EmitOverlapBug(CheckerContext &C, const GRState *state,
367 const Stmt *First, const Stmt *Second) {
368 ExplodedNode *N = C.GenerateSink(state);
369 if (!N)
370 return;
371
372 if (!BT_Overlap)
373 BT_Overlap = new BugType("Unix API", "Improper arguments");
374
375 // Generate a report for this bug.
376 RangedBugReport *report =
377 new RangedBugReport(*BT_Overlap,
378 "Arguments must not be overlapping buffers", N);
379 report->addRange(First->getSourceRange());
380 report->addRange(Second->getSourceRange());
381
382 C.EmitReport(report);
383}
384
Jordy Rose19c5dd12010-07-27 01:37:31 +0000385SVal CStringChecker::GetCStringLength(CheckerContext &C, const GRState *state,
386 const Expr *Ex, SVal Buf) {
387 const MemRegion *MR = Buf.getAsRegion();
388 if (!MR) {
389 // If we can't get a region, see if it's something we /know/ isn't a
390 // C string. In the context of locations, the only time we can issue such
391 // a warning is for labels.
392 if (loc::GotoLabel *Label = dyn_cast<loc::GotoLabel>(&Buf)) {
393 ExplodedNode *N = C.GenerateSink(state);
394 if (N) {
395 if (!BT_NotCString)
396 BT_NotCString = new BuiltinBug("API",
397 "Argument is not a null-terminated string.");
398
399 llvm::SmallString<120> buf;
400 llvm::raw_svector_ostream os(buf);
401 os << "Argument to byte string function is the address of the label '"
402 << Label->getLabel()->getID()->getName()
403 << "', which is not a null-terminated string";
404
405 // Generate a report for this bug.
406 EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
407 os.str(), N);
408
409 report->addRange(Ex->getSourceRange());
410 C.EmitReport(report);
411 }
412
413 return UndefinedVal();
414 }
415
416 // If it's not a region and not a label, it may be a constant location,
417 // or it may be unknown. Just conjure a value as usual (see end of method).
418
419 } else {
420 // If we have a region, strip casts from it and see if we can figure out
421 // its length. For anything we can't figure out, just conjure a value as
422 // usual (see end of method).
423 MR = MR->StripCasts();
424
425 switch (MR->getKind()) {
426 case MemRegion::StringRegionKind: {
427 ValueManager &ValMgr = C.getValueManager();
428 ASTContext &Ctx = ValMgr.getContext();
429 const StringLiteral *Str = cast<StringRegion>(MR)->getStringLiteral();
430
431 // Non-constant string literals may have been changed, so only return a
432 // known value if we know the literal is constant.
433 if (Str->getType().isConstant(Ctx)) {
434 QualType SizeTy = Ctx.getSizeType();
435 return ValMgr.makeIntVal(Str->getByteLength(), SizeTy);
436 }
437
438 // FIXME: Handle the non-constant case. For now, just treat it like any
439 // other initialized region.
440 // FALL-THROUGH
441 }
442 case MemRegion::SymbolicRegionKind:
443 case MemRegion::AllocaRegionKind:
444 case MemRegion::VarRegionKind:
445 case MemRegion::FieldRegionKind:
446 case MemRegion::ObjCIvarRegionKind:
447 // FIXME: These need to be tracked!
448 break;
449 case MemRegion::CompoundLiteralRegionKind:
450 // FIXME: Can we track this? Is it necessary?
451 break;
452 case MemRegion::ElementRegionKind:
453 // FIXME: How can we handle this? It's not good enough to subtract the
454 // offset from the base string length; consider "123\x00567" and &a[5].
455 break;
456 default: {
457 // Other regions (mostly non-data) can't have a reliable C string length.
458 // In this case, an error is emitted and UndefinedVal is returned.
459 // The caller should always be prepared to handle this case.
460 ExplodedNode *N = C.GenerateSink(state);
461 if (N) {
462 if (!BT_NotCString)
463 BT_NotCString = new BuiltinBug("API",
464 "Argument is not a null-terminated string.");
465
466 llvm::SmallString<120> buf;
467 llvm::raw_svector_ostream os(buf);
468
469 os << "Argument to byte string function is ";
470
471 if (SummarizeRegion(os, C.getASTContext(), MR)) {
472 os << ", which is not a null-terminated string";
473 } else {
474 os << "not a null-terminated string";
475 }
476
477 // Generate a report for this bug.
478 EnhancedBugReport *report = new EnhancedBugReport(*BT_NotCString,
479 os.str(), N);
480
481 report->addRange(Ex->getSourceRange());
482 C.EmitReport(report);
483 }
484
485 return UndefinedVal();
486 }
487 }
488 }
489
490 // If we can't track a certain region's C string length, or if we can't get a
491 // region from the SVal, conjure a value, for use in later constraints.
492 unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
493 ValueManager &ValMgr = C.getValueManager();
494 QualType SizeTy = ValMgr.getContext().getSizeType();
495 return ValMgr.getConjuredSymbolVal(getTag(), Ex, SizeTy, Count);
496}
497
498bool CStringChecker::SummarizeRegion(llvm::raw_ostream& os, ASTContext& Ctx,
499 const MemRegion *MR) {
500 const TypedRegion *TR = dyn_cast<TypedRegion>(MR);
501 if (!TR)
502 return false;
503
504 switch (TR->getKind()) {
505 case MemRegion::FunctionTextRegionKind: {
506 const FunctionDecl *FD = cast<FunctionTextRegion>(TR)->getDecl();
507 if (FD)
508 os << "the address of the function '" << FD << "'";
509 else
510 os << "the address of a function";
511 return true;
512 }
513 case MemRegion::BlockTextRegionKind:
514 os << "block text";
515 return true;
516 case MemRegion::BlockDataRegionKind:
517 os << "a block";
518 return true;
519 case MemRegion::CXXThisRegionKind:
520 case MemRegion::CXXObjectRegionKind:
521 os << "a C++ object of type "
522 << TR->getValueType(Ctx).getAsString();
523 return true;
524 case MemRegion::VarRegionKind:
525 os << "a variable of type"
526 << TR->getValueType(Ctx).getAsString();
527 return true;
528 case MemRegion::FieldRegionKind:
529 os << "a field of type "
530 << TR->getValueType(Ctx).getAsString();
531 return true;
532 case MemRegion::ObjCIvarRegionKind:
533 os << "an instance variable of type "
534 << TR->getValueType(Ctx).getAsString();
535 return true;
536 default:
537 return false;
538 }
539}
540
Jordy Rosed325ffb2010-07-08 23:57:29 +0000541//===----------------------------------------------------------------------===//
542// Evaluation of individual function calls.
543//===----------------------------------------------------------------------===//
544
545void CStringChecker::EvalCopyCommon(CheckerContext &C, const GRState *state,
546 const Expr *Size, const Expr *Dest,
547 const Expr *Source, bool Restricted) {
548 // See if the size argument is zero.
549 SVal SizeVal = state->getSVal(Size);
550 QualType SizeTy = Size->getType();
551
552 const GRState *StZeroSize, *StNonZeroSize;
553 llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
554
555 // If the size is zero, there won't be any actual memory access.
556 if (StZeroSize)
557 C.addTransition(StZeroSize);
558
559 // If the size can be nonzero, we have to check the other arguments.
560 if (StNonZeroSize) {
561 state = StNonZeroSize;
562 state = CheckBufferAccess(C, state, Size, Dest, Source);
563 if (Restricted)
564 state = CheckOverlap(C, state, Size, Dest, Source);
565 if (state)
566 C.addTransition(state);
567 }
568}
569
570
571void CStringChecker::EvalMemcpy(CheckerContext &C, const CallExpr *CE) {
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000572 // void *memcpy(void *restrict dst, const void *restrict src, size_t n);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000573 // The return value is the address of the destination buffer.
Jordy Rosed325ffb2010-07-08 23:57:29 +0000574 const Expr *Dest = CE->getArg(0);
575 const GRState *state = C.getState();
576 state = state->BindExpr(CE, state->getSVal(Dest));
577 EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1), true);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000578}
579
Jordy Rosed325ffb2010-07-08 23:57:29 +0000580void CStringChecker::EvalMemmove(CheckerContext &C, const CallExpr *CE) {
581 // void *memmove(void *dst, const void *src, size_t n);
582 // The return value is the address of the destination buffer.
583 const Expr *Dest = CE->getArg(0);
584 const GRState *state = C.getState();
585 state = state->BindExpr(CE, state->getSVal(Dest));
586 EvalCopyCommon(C, state, CE->getArg(2), Dest, CE->getArg(1));
587}
588
589void CStringChecker::EvalBcopy(CheckerContext &C, const CallExpr *CE) {
590 // void bcopy(const void *src, void *dst, size_t n);
591 EvalCopyCommon(C, C.getState(), CE->getArg(2), CE->getArg(1), CE->getArg(0));
592}
593
594void CStringChecker::EvalMemcmp(CheckerContext &C, const CallExpr *CE) {
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000595 // int memcmp(const void *s1, const void *s2, size_t n);
596 const Expr *Left = CE->getArg(0);
597 const Expr *Right = CE->getArg(1);
598 const Expr *Size = CE->getArg(2);
599
600 const GRState *state = C.getState();
601 ValueManager &ValMgr = C.getValueManager();
602 SValuator &SV = ValMgr.getSValuator();
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000603
Jordy Rosed325ffb2010-07-08 23:57:29 +0000604 // See if the size argument is zero.
605 SVal SizeVal = state->getSVal(Size);
606 QualType SizeTy = Size->getType();
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000607
Jordy Rosed325ffb2010-07-08 23:57:29 +0000608 const GRState *StZeroSize, *StNonZeroSize;
609 llvm::tie(StZeroSize, StNonZeroSize) = AssumeZero(C, state, SizeVal, SizeTy);
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000610
Jordy Rosed325ffb2010-07-08 23:57:29 +0000611 // If the size can be zero, the result will be 0 in that case, and we don't
612 // have to check either of the buffers.
613 if (StZeroSize) {
614 state = StZeroSize;
615 state = state->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
616 C.addTransition(state);
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000617 }
618
Jordy Rosed325ffb2010-07-08 23:57:29 +0000619 // If the size can be nonzero, we have to check the other arguments.
620 if (StNonZeroSize) {
621 state = StNonZeroSize;
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000622
Jordy Rosed325ffb2010-07-08 23:57:29 +0000623 // If we know the two buffers are the same, we know the result is 0.
624 // First, get the two buffers' addresses. Another checker will have already
625 // made sure they're not undefined.
626 DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left));
627 DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right));
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000628
Jordy Rosed325ffb2010-07-08 23:57:29 +0000629 // See if they are the same.
630 DefinedOrUnknownSVal SameBuf = SV.EvalEQ(state, LV, RV);
631 const GRState *StSameBuf, *StNotSameBuf;
632 llvm::tie(StSameBuf, StNotSameBuf) = state->Assume(SameBuf);
633
634 // If the two arguments might be the same buffer, we know the result is zero,
635 // and we only need to check one size.
636 if (StSameBuf) {
637 state = StSameBuf;
638 state = CheckBufferAccess(C, state, Size, Left);
639 if (state) {
640 state = StSameBuf->BindExpr(CE, ValMgr.makeZeroVal(CE->getType()));
641 C.addTransition(state);
642 }
643 }
644
645 // If the two arguments might be different buffers, we have to check the
646 // size of both of them.
647 if (StNotSameBuf) {
648 state = StNotSameBuf;
649 state = CheckBufferAccess(C, state, Size, Left, Right);
650 if (state) {
651 // The return value is the comparison result, which we don't know.
652 unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
653 SVal CmpV = ValMgr.getConjuredSymbolVal(NULL, CE, CE->getType(), Count);
654 state = state->BindExpr(CE, CmpV);
655 C.addTransition(state);
656 }
657 }
658 }
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000659}
660
Jordy Rose19c5dd12010-07-27 01:37:31 +0000661void CStringChecker::EvalStrlen(CheckerContext &C, const CallExpr *CE) {
662 // size_t strlen(const char *s);
663 const GRState *state = C.getState();
664 const Expr *Arg = CE->getArg(0);
665 SVal ArgVal = state->getSVal(Arg);
666
667 // Check that the argument is non-null.
668 state = CheckNonNull(C, state, Arg, ArgVal);
669
670 if (state) {
671 // Figure out what the length is, making sure the argument is a C string
672 // (or something similar to a C string). If the argument is valid, the
673 // length will be defined, and we can then set the return value.
674 SVal StrLen = GetCStringLength(C, state, Arg, ArgVal);
675 if (!StrLen.isUndef()) {
676 state = state->BindExpr(CE, StrLen);
677 C.addTransition(state);
678 }
679 }
680}
681
Jordy Rosed325ffb2010-07-08 23:57:29 +0000682//===----------------------------------------------------------------------===//
683// The driver method.
684//===----------------------------------------------------------------------===//
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000685
686bool CStringChecker::EvalCallExpr(CheckerContext &C, const CallExpr *CE) {
687 // Get the callee. All the functions we care about are C functions
688 // with simple identifiers.
689 const GRState *state = C.getState();
690 const Expr *Callee = CE->getCallee();
691 const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl();
692
693 if (!FD)
694 return false;
695
696 // Get the name of the callee. If it's a builtin, strip off the prefix.
697 llvm::StringRef Name = FD->getName();
698 if (Name.startswith("__builtin_"))
699 Name = Name.substr(10);
700
701 FnCheck EvalFunction = llvm::StringSwitch<FnCheck>(Name)
Jordy Rosea6b808c2010-07-07 07:48:06 +0000702 .Cases("memcpy", "__memcpy_chk", &CStringChecker::EvalMemcpy)
Jordy Rosebc56d1f2010-07-07 08:15:01 +0000703 .Cases("memcmp", "bcmp", &CStringChecker::EvalMemcmp)
Jordy Rosea6b808c2010-07-07 07:48:06 +0000704 .Cases("memmove", "__memmove_chk", &CStringChecker::EvalMemmove)
Jordy Rose19c5dd12010-07-27 01:37:31 +0000705 .Case("strlen", &CStringChecker::EvalStrlen)
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000706 .Case("bcopy", &CStringChecker::EvalBcopy)
707 .Default(NULL);
708
Jordy Rosed325ffb2010-07-08 23:57:29 +0000709 // If the callee isn't a string function, let another checker handle it.
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000710 if (!EvalFunction)
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000711 return false;
712
Jordy Rosed325ffb2010-07-08 23:57:29 +0000713 // Check and evaluate the call.
714 (this->*EvalFunction)(C, CE);
Jordy Roseccbf7ee2010-07-06 23:11:01 +0000715 return true;
716}