File: | clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp |
Warning: | line 1028, column 43 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //= CStringChecker.cpp - Checks calls to C string functions --------*- 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 defines CStringChecker, which is an assortment of checks on calls | |||
10 | // to functions in <string.h>. | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" | |||
15 | #include "InterCheckerAPI.h" | |||
16 | #include "clang/Basic/CharInfo.h" | |||
17 | #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" | |||
18 | #include "clang/StaticAnalyzer/Core/Checker.h" | |||
19 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" | |||
20 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" | |||
21 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" | |||
22 | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" | |||
23 | #include "llvm/ADT/STLExtras.h" | |||
24 | #include "llvm/ADT/SmallString.h" | |||
25 | #include "llvm/Support/raw_ostream.h" | |||
26 | ||||
27 | using namespace clang; | |||
28 | using namespace ento; | |||
29 | ||||
30 | namespace { | |||
31 | enum class ConcatFnKind { none = 0, strcat = 1, strlcat = 2 }; | |||
32 | class CStringChecker : public Checker< eval::Call, | |||
33 | check::PreStmt<DeclStmt>, | |||
34 | check::LiveSymbols, | |||
35 | check::DeadSymbols, | |||
36 | check::RegionChanges | |||
37 | > { | |||
38 | mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap, | |||
39 | BT_NotCString, BT_AdditionOverflow; | |||
40 | ||||
41 | mutable const char *CurrentFunctionDescription; | |||
42 | ||||
43 | public: | |||
44 | /// The filter is used to filter out the diagnostics which are not enabled by | |||
45 | /// the user. | |||
46 | struct CStringChecksFilter { | |||
47 | DefaultBool CheckCStringNullArg; | |||
48 | DefaultBool CheckCStringOutOfBounds; | |||
49 | DefaultBool CheckCStringBufferOverlap; | |||
50 | DefaultBool CheckCStringNotNullTerm; | |||
51 | ||||
52 | CheckerNameRef CheckNameCStringNullArg; | |||
53 | CheckerNameRef CheckNameCStringOutOfBounds; | |||
54 | CheckerNameRef CheckNameCStringBufferOverlap; | |||
55 | CheckerNameRef CheckNameCStringNotNullTerm; | |||
56 | }; | |||
57 | ||||
58 | CStringChecksFilter Filter; | |||
59 | ||||
60 | static void *getTag() { static int tag; return &tag; } | |||
61 | ||||
62 | bool evalCall(const CallEvent &Call, CheckerContext &C) const; | |||
63 | void checkPreStmt(const DeclStmt *DS, CheckerContext &C) const; | |||
64 | void checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const; | |||
65 | void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const; | |||
66 | ||||
67 | ProgramStateRef | |||
68 | checkRegionChanges(ProgramStateRef state, | |||
69 | const InvalidatedSymbols *, | |||
70 | ArrayRef<const MemRegion *> ExplicitRegions, | |||
71 | ArrayRef<const MemRegion *> Regions, | |||
72 | const LocationContext *LCtx, | |||
73 | const CallEvent *Call) const; | |||
74 | ||||
75 | typedef void (CStringChecker::*FnCheck)(CheckerContext &, | |||
76 | const CallExpr *) const; | |||
77 | CallDescriptionMap<FnCheck> Callbacks = { | |||
78 | {{CDF_MaybeBuiltin, "memcpy", 3}, &CStringChecker::evalMemcpy}, | |||
79 | {{CDF_MaybeBuiltin, "mempcpy", 3}, &CStringChecker::evalMempcpy}, | |||
80 | {{CDF_MaybeBuiltin, "memcmp", 3}, &CStringChecker::evalMemcmp}, | |||
81 | {{CDF_MaybeBuiltin, "memmove", 3}, &CStringChecker::evalMemmove}, | |||
82 | {{CDF_MaybeBuiltin, "memset", 3}, &CStringChecker::evalMemset}, | |||
83 | {{CDF_MaybeBuiltin, "explicit_memset", 3}, &CStringChecker::evalMemset}, | |||
84 | {{CDF_MaybeBuiltin, "strcpy", 2}, &CStringChecker::evalStrcpy}, | |||
85 | {{CDF_MaybeBuiltin, "strncpy", 3}, &CStringChecker::evalStrncpy}, | |||
86 | {{CDF_MaybeBuiltin, "stpcpy", 2}, &CStringChecker::evalStpcpy}, | |||
87 | {{CDF_MaybeBuiltin, "strlcpy", 3}, &CStringChecker::evalStrlcpy}, | |||
88 | {{CDF_MaybeBuiltin, "strcat", 2}, &CStringChecker::evalStrcat}, | |||
89 | {{CDF_MaybeBuiltin, "strncat", 3}, &CStringChecker::evalStrncat}, | |||
90 | {{CDF_MaybeBuiltin, "strlcat", 3}, &CStringChecker::evalStrlcat}, | |||
91 | {{CDF_MaybeBuiltin, "strlen", 1}, &CStringChecker::evalstrLength}, | |||
92 | {{CDF_MaybeBuiltin, "strnlen", 2}, &CStringChecker::evalstrnLength}, | |||
93 | {{CDF_MaybeBuiltin, "strcmp", 2}, &CStringChecker::evalStrcmp}, | |||
94 | {{CDF_MaybeBuiltin, "strncmp", 3}, &CStringChecker::evalStrncmp}, | |||
95 | {{CDF_MaybeBuiltin, "strcasecmp", 2}, &CStringChecker::evalStrcasecmp}, | |||
96 | {{CDF_MaybeBuiltin, "strncasecmp", 3}, &CStringChecker::evalStrncasecmp}, | |||
97 | {{CDF_MaybeBuiltin, "strsep", 2}, &CStringChecker::evalStrsep}, | |||
98 | {{CDF_MaybeBuiltin, "bcopy", 3}, &CStringChecker::evalBcopy}, | |||
99 | {{CDF_MaybeBuiltin, "bcmp", 3}, &CStringChecker::evalMemcmp}, | |||
100 | {{CDF_MaybeBuiltin, "bzero", 2}, &CStringChecker::evalBzero}, | |||
101 | {{CDF_MaybeBuiltin, "explicit_bzero", 2}, &CStringChecker::evalBzero}, | |||
102 | }; | |||
103 | ||||
104 | // These require a bit of special handling. | |||
105 | CallDescription StdCopy{{"std", "copy"}, 3}, | |||
106 | StdCopyBackward{{"std", "copy_backward"}, 3}; | |||
107 | ||||
108 | FnCheck identifyCall(const CallEvent &Call, CheckerContext &C) const; | |||
109 | void evalMemcpy(CheckerContext &C, const CallExpr *CE) const; | |||
110 | void evalMempcpy(CheckerContext &C, const CallExpr *CE) const; | |||
111 | void evalMemmove(CheckerContext &C, const CallExpr *CE) const; | |||
112 | void evalBcopy(CheckerContext &C, const CallExpr *CE) const; | |||
113 | void evalCopyCommon(CheckerContext &C, const CallExpr *CE, | |||
114 | ProgramStateRef state, | |||
115 | const Expr *Size, | |||
116 | const Expr *Source, | |||
117 | const Expr *Dest, | |||
118 | bool Restricted = false, | |||
119 | bool IsMempcpy = false) const; | |||
120 | ||||
121 | void evalMemcmp(CheckerContext &C, const CallExpr *CE) const; | |||
122 | ||||
123 | void evalstrLength(CheckerContext &C, const CallExpr *CE) const; | |||
124 | void evalstrnLength(CheckerContext &C, const CallExpr *CE) const; | |||
125 | void evalstrLengthCommon(CheckerContext &C, | |||
126 | const CallExpr *CE, | |||
127 | bool IsStrnlen = false) const; | |||
128 | ||||
129 | void evalStrcpy(CheckerContext &C, const CallExpr *CE) const; | |||
130 | void evalStrncpy(CheckerContext &C, const CallExpr *CE) const; | |||
131 | void evalStpcpy(CheckerContext &C, const CallExpr *CE) const; | |||
132 | void evalStrlcpy(CheckerContext &C, const CallExpr *CE) const; | |||
133 | void evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool ReturnEnd, | |||
134 | bool IsBounded, ConcatFnKind appendK, | |||
135 | bool returnPtr = true) const; | |||
136 | ||||
137 | void evalStrcat(CheckerContext &C, const CallExpr *CE) const; | |||
138 | void evalStrncat(CheckerContext &C, const CallExpr *CE) const; | |||
139 | void evalStrlcat(CheckerContext &C, const CallExpr *CE) const; | |||
140 | ||||
141 | void evalStrcmp(CheckerContext &C, const CallExpr *CE) const; | |||
142 | void evalStrncmp(CheckerContext &C, const CallExpr *CE) const; | |||
143 | void evalStrcasecmp(CheckerContext &C, const CallExpr *CE) const; | |||
144 | void evalStrncasecmp(CheckerContext &C, const CallExpr *CE) const; | |||
145 | void evalStrcmpCommon(CheckerContext &C, | |||
146 | const CallExpr *CE, | |||
147 | bool IsBounded = false, | |||
148 | bool IgnoreCase = false) const; | |||
149 | ||||
150 | void evalStrsep(CheckerContext &C, const CallExpr *CE) const; | |||
151 | ||||
152 | void evalStdCopy(CheckerContext &C, const CallExpr *CE) const; | |||
153 | void evalStdCopyBackward(CheckerContext &C, const CallExpr *CE) const; | |||
154 | void evalStdCopyCommon(CheckerContext &C, const CallExpr *CE) const; | |||
155 | void evalMemset(CheckerContext &C, const CallExpr *CE) const; | |||
156 | void evalBzero(CheckerContext &C, const CallExpr *CE) const; | |||
157 | ||||
158 | // Utility methods | |||
159 | std::pair<ProgramStateRef , ProgramStateRef > | |||
160 | static assumeZero(CheckerContext &C, | |||
161 | ProgramStateRef state, SVal V, QualType Ty); | |||
162 | ||||
163 | static ProgramStateRef setCStringLength(ProgramStateRef state, | |||
164 | const MemRegion *MR, | |||
165 | SVal strLength); | |||
166 | static SVal getCStringLengthForRegion(CheckerContext &C, | |||
167 | ProgramStateRef &state, | |||
168 | const Expr *Ex, | |||
169 | const MemRegion *MR, | |||
170 | bool hypothetical); | |||
171 | SVal getCStringLength(CheckerContext &C, | |||
172 | ProgramStateRef &state, | |||
173 | const Expr *Ex, | |||
174 | SVal Buf, | |||
175 | bool hypothetical = false) const; | |||
176 | ||||
177 | const StringLiteral *getCStringLiteral(CheckerContext &C, | |||
178 | ProgramStateRef &state, | |||
179 | const Expr *expr, | |||
180 | SVal val) const; | |||
181 | ||||
182 | static ProgramStateRef InvalidateBuffer(CheckerContext &C, | |||
183 | ProgramStateRef state, | |||
184 | const Expr *Ex, SVal V, | |||
185 | bool IsSourceBuffer, | |||
186 | const Expr *Size); | |||
187 | ||||
188 | static bool SummarizeRegion(raw_ostream &os, ASTContext &Ctx, | |||
189 | const MemRegion *MR); | |||
190 | ||||
191 | static bool memsetAux(const Expr *DstBuffer, SVal CharE, | |||
192 | const Expr *Size, CheckerContext &C, | |||
193 | ProgramStateRef &State); | |||
194 | ||||
195 | // Re-usable checks | |||
196 | ProgramStateRef checkNonNull(CheckerContext &C, | |||
197 | ProgramStateRef state, | |||
198 | const Expr *S, | |||
199 | SVal l, | |||
200 | unsigned IdxOfArg) const; | |||
201 | ProgramStateRef CheckLocation(CheckerContext &C, | |||
202 | ProgramStateRef state, | |||
203 | const Expr *S, | |||
204 | SVal l, | |||
205 | const char *message = nullptr) const; | |||
206 | ProgramStateRef CheckBufferAccess(CheckerContext &C, | |||
207 | ProgramStateRef state, | |||
208 | const Expr *Size, | |||
209 | const Expr *FirstBuf, | |||
210 | const Expr *SecondBuf, | |||
211 | const char *firstMessage = nullptr, | |||
212 | const char *secondMessage = nullptr, | |||
213 | bool WarnAboutSize = false) const; | |||
214 | ||||
215 | ProgramStateRef CheckBufferAccess(CheckerContext &C, | |||
216 | ProgramStateRef state, | |||
217 | const Expr *Size, | |||
218 | const Expr *Buf, | |||
219 | const char *message = nullptr, | |||
220 | bool WarnAboutSize = false) const { | |||
221 | // This is a convenience overload. | |||
222 | return CheckBufferAccess(C, state, Size, Buf, nullptr, message, nullptr, | |||
223 | WarnAboutSize); | |||
224 | } | |||
225 | ProgramStateRef CheckOverlap(CheckerContext &C, | |||
226 | ProgramStateRef state, | |||
227 | const Expr *Size, | |||
228 | const Expr *First, | |||
229 | const Expr *Second) const; | |||
230 | void emitOverlapBug(CheckerContext &C, | |||
231 | ProgramStateRef state, | |||
232 | const Stmt *First, | |||
233 | const Stmt *Second) const; | |||
234 | ||||
235 | void emitNullArgBug(CheckerContext &C, ProgramStateRef State, const Stmt *S, | |||
236 | StringRef WarningMsg) const; | |||
237 | void emitOutOfBoundsBug(CheckerContext &C, ProgramStateRef State, | |||
238 | const Stmt *S, StringRef WarningMsg) const; | |||
239 | void emitNotCStringBug(CheckerContext &C, ProgramStateRef State, | |||
240 | const Stmt *S, StringRef WarningMsg) const; | |||
241 | void emitAdditionOverflowBug(CheckerContext &C, ProgramStateRef State) const; | |||
242 | ||||
243 | ProgramStateRef checkAdditionOverflow(CheckerContext &C, | |||
244 | ProgramStateRef state, | |||
245 | NonLoc left, | |||
246 | NonLoc right) const; | |||
247 | ||||
248 | // Return true if the destination buffer of the copy function may be in bound. | |||
249 | // Expects SVal of Size to be positive and unsigned. | |||
250 | // Expects SVal of FirstBuf to be a FieldRegion. | |||
251 | static bool IsFirstBufInBound(CheckerContext &C, | |||
252 | ProgramStateRef state, | |||
253 | const Expr *FirstBuf, | |||
254 | const Expr *Size); | |||
255 | }; | |||
256 | ||||
257 | } //end anonymous namespace | |||
258 | ||||
259 | REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal)namespace { class CStringLength {}; using CStringLengthTy = llvm ::ImmutableMap<const MemRegion *, SVal>; } namespace clang { namespace ento { template <> struct ProgramStateTrait <CStringLength> : public ProgramStatePartialTrait<CStringLengthTy > { static void *GDMIndex() { static int Index; return & Index; } }; } } | |||
260 | ||||
261 | //===----------------------------------------------------------------------===// | |||
262 | // Individual checks and utility methods. | |||
263 | //===----------------------------------------------------------------------===// | |||
264 | ||||
265 | std::pair<ProgramStateRef , ProgramStateRef > | |||
266 | CStringChecker::assumeZero(CheckerContext &C, ProgramStateRef state, SVal V, | |||
267 | QualType Ty) { | |||
268 | Optional<DefinedSVal> val = V.getAs<DefinedSVal>(); | |||
269 | if (!val) | |||
270 | return std::pair<ProgramStateRef , ProgramStateRef >(state, state); | |||
271 | ||||
272 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
273 | DefinedOrUnknownSVal zero = svalBuilder.makeZeroVal(Ty); | |||
274 | return state->assume(svalBuilder.evalEQ(state, *val, zero)); | |||
275 | } | |||
276 | ||||
277 | ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C, | |||
278 | ProgramStateRef state, | |||
279 | const Expr *S, SVal l, | |||
280 | unsigned IdxOfArg) const { | |||
281 | // If a previous check has failed, propagate the failure. | |||
282 | if (!state) | |||
283 | return nullptr; | |||
284 | ||||
285 | ProgramStateRef stateNull, stateNonNull; | |||
286 | std::tie(stateNull, stateNonNull) = assumeZero(C, state, l, S->getType()); | |||
287 | ||||
288 | if (stateNull && !stateNonNull) { | |||
289 | if (Filter.CheckCStringNullArg) { | |||
290 | SmallString<80> buf; | |||
291 | llvm::raw_svector_ostream OS(buf); | |||
292 | assert(CurrentFunctionDescription)((CurrentFunctionDescription) ? static_cast<void> (0) : __assert_fail ("CurrentFunctionDescription", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 292, __PRETTY_FUNCTION__)); | |||
293 | OS << "Null pointer passed as " << IdxOfArg | |||
294 | << llvm::getOrdinalSuffix(IdxOfArg) << " argument to " | |||
295 | << CurrentFunctionDescription; | |||
296 | ||||
297 | emitNullArgBug(C, stateNull, S, OS.str()); | |||
298 | } | |||
299 | return nullptr; | |||
300 | } | |||
301 | ||||
302 | // From here on, assume that the value is non-null. | |||
303 | assert(stateNonNull)((stateNonNull) ? static_cast<void> (0) : __assert_fail ("stateNonNull", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 303, __PRETTY_FUNCTION__)); | |||
304 | return stateNonNull; | |||
305 | } | |||
306 | ||||
307 | // FIXME: This was originally copied from ArrayBoundChecker.cpp. Refactor? | |||
308 | ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, | |||
309 | ProgramStateRef state, | |||
310 | const Expr *S, SVal l, | |||
311 | const char *warningMsg) const { | |||
312 | // If a previous check has failed, propagate the failure. | |||
313 | if (!state) | |||
314 | return nullptr; | |||
315 | ||||
316 | // Check for out of bound array element access. | |||
317 | const MemRegion *R = l.getAsRegion(); | |||
318 | if (!R) | |||
319 | return state; | |||
320 | ||||
321 | const ElementRegion *ER = dyn_cast<ElementRegion>(R); | |||
322 | if (!ER) | |||
323 | return state; | |||
324 | ||||
325 | if (ER->getValueType() != C.getASTContext().CharTy) | |||
326 | return state; | |||
327 | ||||
328 | // Get the size of the array. | |||
329 | const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); | |||
330 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
331 | SVal Extent = | |||
332 | svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); | |||
333 | DefinedOrUnknownSVal Size = Extent.castAs<DefinedOrUnknownSVal>(); | |||
334 | ||||
335 | // Get the index of the accessed element. | |||
336 | DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); | |||
337 | ||||
338 | ProgramStateRef StInBound = state->assumeInBound(Idx, Size, true); | |||
339 | ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false); | |||
340 | if (StOutBound && !StInBound) { | |||
341 | // These checks are either enabled by the CString out-of-bounds checker | |||
342 | // explicitly or implicitly by the Malloc checker. | |||
343 | // In the latter case we only do modeling but do not emit warning. | |||
344 | if (!Filter.CheckCStringOutOfBounds) | |||
345 | return nullptr; | |||
346 | // Emit a bug report. | |||
347 | if (warningMsg) { | |||
348 | emitOutOfBoundsBug(C, StOutBound, S, warningMsg); | |||
349 | } else { | |||
350 | assert(CurrentFunctionDescription)((CurrentFunctionDescription) ? static_cast<void> (0) : __assert_fail ("CurrentFunctionDescription", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 350, __PRETTY_FUNCTION__)); | |||
351 | assert(CurrentFunctionDescription[0] != '\0')((CurrentFunctionDescription[0] != '\0') ? static_cast<void > (0) : __assert_fail ("CurrentFunctionDescription[0] != '\\0'" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 351, __PRETTY_FUNCTION__)); | |||
352 | ||||
353 | SmallString<80> buf; | |||
354 | llvm::raw_svector_ostream os(buf); | |||
355 | os << toUppercase(CurrentFunctionDescription[0]) | |||
356 | << &CurrentFunctionDescription[1] | |||
357 | << " accesses out-of-bound array element"; | |||
358 | emitOutOfBoundsBug(C, StOutBound, S, os.str()); | |||
359 | } | |||
360 | return nullptr; | |||
361 | } | |||
362 | ||||
363 | // Array bound check succeeded. From this point forward the array bound | |||
364 | // should always succeed. | |||
365 | return StInBound; | |||
366 | } | |||
367 | ||||
368 | ProgramStateRef CStringChecker::CheckBufferAccess(CheckerContext &C, | |||
369 | ProgramStateRef state, | |||
370 | const Expr *Size, | |||
371 | const Expr *FirstBuf, | |||
372 | const Expr *SecondBuf, | |||
373 | const char *firstMessage, | |||
374 | const char *secondMessage, | |||
375 | bool WarnAboutSize) const { | |||
376 | // If a previous check has failed, propagate the failure. | |||
377 | if (!state) | |||
378 | return nullptr; | |||
379 | ||||
380 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
381 | ASTContext &Ctx = svalBuilder.getContext(); | |||
382 | const LocationContext *LCtx = C.getLocationContext(); | |||
383 | ||||
384 | QualType sizeTy = Size->getType(); | |||
385 | QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); | |||
386 | ||||
387 | // Check that the first buffer is non-null. | |||
388 | SVal BufVal = C.getSVal(FirstBuf); | |||
389 | state = checkNonNull(C, state, FirstBuf, BufVal, 1); | |||
390 | if (!state) | |||
391 | return nullptr; | |||
392 | ||||
393 | // If out-of-bounds checking is turned off, skip the rest. | |||
394 | if (!Filter.CheckCStringOutOfBounds) | |||
395 | return state; | |||
396 | ||||
397 | // Get the access length and make sure it is known. | |||
398 | // FIXME: This assumes the caller has already checked that the access length | |||
399 | // is positive. And that it's unsigned. | |||
400 | SVal LengthVal = C.getSVal(Size); | |||
401 | Optional<NonLoc> Length = LengthVal.getAs<NonLoc>(); | |||
402 | if (!Length) | |||
403 | return state; | |||
404 | ||||
405 | // Compute the offset of the last element to be accessed: size-1. | |||
406 | NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>(); | |||
407 | SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy); | |||
408 | if (Offset.isUnknown()) | |||
409 | return nullptr; | |||
410 | NonLoc LastOffset = Offset.castAs<NonLoc>(); | |||
411 | ||||
412 | // Check that the first buffer is sufficiently long. | |||
413 | SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); | |||
414 | if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) { | |||
415 | const Expr *warningExpr = (WarnAboutSize ? Size : FirstBuf); | |||
416 | ||||
417 | SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, | |||
418 | LastOffset, PtrTy); | |||
419 | state = CheckLocation(C, state, warningExpr, BufEnd, firstMessage); | |||
420 | ||||
421 | // If the buffer isn't large enough, abort. | |||
422 | if (!state) | |||
423 | return nullptr; | |||
424 | } | |||
425 | ||||
426 | // If there's a second buffer, check it as well. | |||
427 | if (SecondBuf) { | |||
428 | BufVal = state->getSVal(SecondBuf, LCtx); | |||
429 | state = checkNonNull(C, state, SecondBuf, BufVal, 2); | |||
430 | if (!state) | |||
431 | return nullptr; | |||
432 | ||||
433 | BufStart = svalBuilder.evalCast(BufVal, PtrTy, SecondBuf->getType()); | |||
434 | if (Optional<Loc> BufLoc = BufStart.getAs<Loc>()) { | |||
435 | const Expr *warningExpr = (WarnAboutSize ? Size : SecondBuf); | |||
436 | ||||
437 | SVal BufEnd = svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, | |||
438 | LastOffset, PtrTy); | |||
439 | state = CheckLocation(C, state, warningExpr, BufEnd, secondMessage); | |||
440 | } | |||
441 | } | |||
442 | ||||
443 | // Large enough or not, return this state! | |||
444 | return state; | |||
445 | } | |||
446 | ||||
447 | ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C, | |||
448 | ProgramStateRef state, | |||
449 | const Expr *Size, | |||
450 | const Expr *First, | |||
451 | const Expr *Second) const { | |||
452 | if (!Filter.CheckCStringBufferOverlap) | |||
453 | return state; | |||
454 | ||||
455 | // Do a simple check for overlap: if the two arguments are from the same | |||
456 | // buffer, see if the end of the first is greater than the start of the second | |||
457 | // or vice versa. | |||
458 | ||||
459 | // If a previous check has failed, propagate the failure. | |||
460 | if (!state) | |||
461 | return nullptr; | |||
462 | ||||
463 | ProgramStateRef stateTrue, stateFalse; | |||
464 | ||||
465 | // Get the buffer values and make sure they're known locations. | |||
466 | const LocationContext *LCtx = C.getLocationContext(); | |||
467 | SVal firstVal = state->getSVal(First, LCtx); | |||
468 | SVal secondVal = state->getSVal(Second, LCtx); | |||
469 | ||||
470 | Optional<Loc> firstLoc = firstVal.getAs<Loc>(); | |||
471 | if (!firstLoc) | |||
472 | return state; | |||
473 | ||||
474 | Optional<Loc> secondLoc = secondVal.getAs<Loc>(); | |||
475 | if (!secondLoc) | |||
476 | return state; | |||
477 | ||||
478 | // Are the two values the same? | |||
479 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
480 | std::tie(stateTrue, stateFalse) = | |||
481 | state->assume(svalBuilder.evalEQ(state, *firstLoc, *secondLoc)); | |||
482 | ||||
483 | if (stateTrue && !stateFalse) { | |||
484 | // If the values are known to be equal, that's automatically an overlap. | |||
485 | emitOverlapBug(C, stateTrue, First, Second); | |||
486 | return nullptr; | |||
487 | } | |||
488 | ||||
489 | // assume the two expressions are not equal. | |||
490 | assert(stateFalse)((stateFalse) ? static_cast<void> (0) : __assert_fail ( "stateFalse", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 490, __PRETTY_FUNCTION__)); | |||
491 | state = stateFalse; | |||
492 | ||||
493 | // Which value comes first? | |||
494 | QualType cmpTy = svalBuilder.getConditionType(); | |||
495 | SVal reverse = svalBuilder.evalBinOpLL(state, BO_GT, | |||
496 | *firstLoc, *secondLoc, cmpTy); | |||
497 | Optional<DefinedOrUnknownSVal> reverseTest = | |||
498 | reverse.getAs<DefinedOrUnknownSVal>(); | |||
499 | if (!reverseTest) | |||
500 | return state; | |||
501 | ||||
502 | std::tie(stateTrue, stateFalse) = state->assume(*reverseTest); | |||
503 | if (stateTrue) { | |||
504 | if (stateFalse) { | |||
505 | // If we don't know which one comes first, we can't perform this test. | |||
506 | return state; | |||
507 | } else { | |||
508 | // Switch the values so that firstVal is before secondVal. | |||
509 | std::swap(firstLoc, secondLoc); | |||
510 | ||||
511 | // Switch the Exprs as well, so that they still correspond. | |||
512 | std::swap(First, Second); | |||
513 | } | |||
514 | } | |||
515 | ||||
516 | // Get the length, and make sure it too is known. | |||
517 | SVal LengthVal = state->getSVal(Size, LCtx); | |||
518 | Optional<NonLoc> Length = LengthVal.getAs<NonLoc>(); | |||
519 | if (!Length) | |||
520 | return state; | |||
521 | ||||
522 | // Convert the first buffer's start address to char*. | |||
523 | // Bail out if the cast fails. | |||
524 | ASTContext &Ctx = svalBuilder.getContext(); | |||
525 | QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); | |||
526 | SVal FirstStart = svalBuilder.evalCast(*firstLoc, CharPtrTy, | |||
527 | First->getType()); | |||
528 | Optional<Loc> FirstStartLoc = FirstStart.getAs<Loc>(); | |||
529 | if (!FirstStartLoc) | |||
530 | return state; | |||
531 | ||||
532 | // Compute the end of the first buffer. Bail out if THAT fails. | |||
533 | SVal FirstEnd = svalBuilder.evalBinOpLN(state, BO_Add, | |||
534 | *FirstStartLoc, *Length, CharPtrTy); | |||
535 | Optional<Loc> FirstEndLoc = FirstEnd.getAs<Loc>(); | |||
536 | if (!FirstEndLoc) | |||
537 | return state; | |||
538 | ||||
539 | // Is the end of the first buffer past the start of the second buffer? | |||
540 | SVal Overlap = svalBuilder.evalBinOpLL(state, BO_GT, | |||
541 | *FirstEndLoc, *secondLoc, cmpTy); | |||
542 | Optional<DefinedOrUnknownSVal> OverlapTest = | |||
543 | Overlap.getAs<DefinedOrUnknownSVal>(); | |||
544 | if (!OverlapTest) | |||
545 | return state; | |||
546 | ||||
547 | std::tie(stateTrue, stateFalse) = state->assume(*OverlapTest); | |||
548 | ||||
549 | if (stateTrue && !stateFalse) { | |||
550 | // Overlap! | |||
551 | emitOverlapBug(C, stateTrue, First, Second); | |||
552 | return nullptr; | |||
553 | } | |||
554 | ||||
555 | // assume the two expressions don't overlap. | |||
556 | assert(stateFalse)((stateFalse) ? static_cast<void> (0) : __assert_fail ( "stateFalse", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 556, __PRETTY_FUNCTION__)); | |||
557 | return stateFalse; | |||
558 | } | |||
559 | ||||
560 | void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state, | |||
561 | const Stmt *First, const Stmt *Second) const { | |||
562 | ExplodedNode *N = C.generateErrorNode(state); | |||
563 | if (!N) | |||
564 | return; | |||
565 | ||||
566 | if (!BT_Overlap) | |||
567 | BT_Overlap.reset(new BugType(Filter.CheckNameCStringBufferOverlap, | |||
568 | categories::UnixAPI, "Improper arguments")); | |||
569 | ||||
570 | // Generate a report for this bug. | |||
571 | auto report = std::make_unique<PathSensitiveBugReport>( | |||
572 | *BT_Overlap, "Arguments must not be overlapping buffers", N); | |||
573 | report->addRange(First->getSourceRange()); | |||
574 | report->addRange(Second->getSourceRange()); | |||
575 | ||||
576 | C.emitReport(std::move(report)); | |||
577 | } | |||
578 | ||||
579 | void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State, | |||
580 | const Stmt *S, StringRef WarningMsg) const { | |||
581 | if (ExplodedNode *N = C.generateErrorNode(State)) { | |||
582 | if (!BT_Null) | |||
583 | BT_Null.reset(new BuiltinBug( | |||
584 | Filter.CheckNameCStringNullArg, categories::UnixAPI, | |||
585 | "Null pointer argument in call to byte string function")); | |||
586 | ||||
587 | BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Null.get()); | |||
588 | auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N); | |||
589 | Report->addRange(S->getSourceRange()); | |||
590 | if (const auto *Ex = dyn_cast<Expr>(S)) | |||
591 | bugreporter::trackExpressionValue(N, Ex, *Report); | |||
592 | C.emitReport(std::move(Report)); | |||
593 | } | |||
594 | } | |||
595 | ||||
596 | void CStringChecker::emitOutOfBoundsBug(CheckerContext &C, | |||
597 | ProgramStateRef State, const Stmt *S, | |||
598 | StringRef WarningMsg) const { | |||
599 | if (ExplodedNode *N = C.generateErrorNode(State)) { | |||
600 | if (!BT_Bounds) | |||
601 | BT_Bounds.reset(new BuiltinBug( | |||
602 | Filter.CheckCStringOutOfBounds ? Filter.CheckNameCStringOutOfBounds | |||
603 | : Filter.CheckNameCStringNullArg, | |||
604 | "Out-of-bound array access", | |||
605 | "Byte string function accesses out-of-bound array element")); | |||
606 | ||||
607 | BuiltinBug *BT = static_cast<BuiltinBug *>(BT_Bounds.get()); | |||
608 | ||||
609 | // FIXME: It would be nice to eventually make this diagnostic more clear, | |||
610 | // e.g., by referencing the original declaration or by saying *why* this | |||
611 | // reference is outside the range. | |||
612 | auto Report = std::make_unique<PathSensitiveBugReport>(*BT, WarningMsg, N); | |||
613 | Report->addRange(S->getSourceRange()); | |||
614 | C.emitReport(std::move(Report)); | |||
615 | } | |||
616 | } | |||
617 | ||||
618 | void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State, | |||
619 | const Stmt *S, | |||
620 | StringRef WarningMsg) const { | |||
621 | if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) { | |||
622 | if (!BT_NotCString) | |||
623 | BT_NotCString.reset(new BuiltinBug( | |||
624 | Filter.CheckNameCStringNotNullTerm, categories::UnixAPI, | |||
625 | "Argument is not a null-terminated string.")); | |||
626 | ||||
627 | auto Report = | |||
628 | std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N); | |||
629 | ||||
630 | Report->addRange(S->getSourceRange()); | |||
631 | C.emitReport(std::move(Report)); | |||
632 | } | |||
633 | } | |||
634 | ||||
635 | void CStringChecker::emitAdditionOverflowBug(CheckerContext &C, | |||
636 | ProgramStateRef State) const { | |||
637 | if (ExplodedNode *N = C.generateErrorNode(State)) { | |||
638 | if (!BT_NotCString) | |||
639 | BT_NotCString.reset( | |||
640 | new BuiltinBug(Filter.CheckNameCStringOutOfBounds, "API", | |||
641 | "Sum of expressions causes overflow.")); | |||
642 | ||||
643 | // This isn't a great error message, but this should never occur in real | |||
644 | // code anyway -- you'd have to create a buffer longer than a size_t can | |||
645 | // represent, which is sort of a contradiction. | |||
646 | const char *WarningMsg = | |||
647 | "This expression will create a string whose length is too big to " | |||
648 | "be represented as a size_t"; | |||
649 | ||||
650 | auto Report = | |||
651 | std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N); | |||
652 | C.emitReport(std::move(Report)); | |||
653 | } | |||
654 | } | |||
655 | ||||
656 | ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C, | |||
657 | ProgramStateRef state, | |||
658 | NonLoc left, | |||
659 | NonLoc right) const { | |||
660 | // If out-of-bounds checking is turned off, skip the rest. | |||
661 | if (!Filter.CheckCStringOutOfBounds) | |||
662 | return state; | |||
663 | ||||
664 | // If a previous check has failed, propagate the failure. | |||
665 | if (!state) | |||
666 | return nullptr; | |||
667 | ||||
668 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
669 | BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); | |||
670 | ||||
671 | QualType sizeTy = svalBuilder.getContext().getSizeType(); | |||
672 | const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); | |||
673 | NonLoc maxVal = svalBuilder.makeIntVal(maxValInt); | |||
674 | ||||
675 | SVal maxMinusRight; | |||
676 | if (right.getAs<nonloc::ConcreteInt>()) { | |||
677 | maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, right, | |||
678 | sizeTy); | |||
679 | } else { | |||
680 | // Try switching the operands. (The order of these two assignments is | |||
681 | // important!) | |||
682 | maxMinusRight = svalBuilder.evalBinOpNN(state, BO_Sub, maxVal, left, | |||
683 | sizeTy); | |||
684 | left = right; | |||
685 | } | |||
686 | ||||
687 | if (Optional<NonLoc> maxMinusRightNL = maxMinusRight.getAs<NonLoc>()) { | |||
688 | QualType cmpTy = svalBuilder.getConditionType(); | |||
689 | // If left > max - right, we have an overflow. | |||
690 | SVal willOverflow = svalBuilder.evalBinOpNN(state, BO_GT, left, | |||
691 | *maxMinusRightNL, cmpTy); | |||
692 | ||||
693 | ProgramStateRef stateOverflow, stateOkay; | |||
694 | std::tie(stateOverflow, stateOkay) = | |||
695 | state->assume(willOverflow.castAs<DefinedOrUnknownSVal>()); | |||
696 | ||||
697 | if (stateOverflow && !stateOkay) { | |||
698 | // We have an overflow. Emit a bug report. | |||
699 | emitAdditionOverflowBug(C, stateOverflow); | |||
700 | return nullptr; | |||
701 | } | |||
702 | ||||
703 | // From now on, assume an overflow didn't occur. | |||
704 | assert(stateOkay)((stateOkay) ? static_cast<void> (0) : __assert_fail ("stateOkay" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 704, __PRETTY_FUNCTION__)); | |||
705 | state = stateOkay; | |||
706 | } | |||
707 | ||||
708 | return state; | |||
709 | } | |||
710 | ||||
711 | ProgramStateRef CStringChecker::setCStringLength(ProgramStateRef state, | |||
712 | const MemRegion *MR, | |||
713 | SVal strLength) { | |||
714 | assert(!strLength.isUndef() && "Attempt to set an undefined string length")((!strLength.isUndef() && "Attempt to set an undefined string length" ) ? static_cast<void> (0) : __assert_fail ("!strLength.isUndef() && \"Attempt to set an undefined string length\"" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 714, __PRETTY_FUNCTION__)); | |||
715 | ||||
716 | MR = MR->StripCasts(); | |||
717 | ||||
718 | switch (MR->getKind()) { | |||
719 | case MemRegion::StringRegionKind: | |||
720 | // FIXME: This can happen if we strcpy() into a string region. This is | |||
721 | // undefined [C99 6.4.5p6], but we should still warn about it. | |||
722 | return state; | |||
723 | ||||
724 | case MemRegion::SymbolicRegionKind: | |||
725 | case MemRegion::AllocaRegionKind: | |||
726 | case MemRegion::VarRegionKind: | |||
727 | case MemRegion::FieldRegionKind: | |||
728 | case MemRegion::ObjCIvarRegionKind: | |||
729 | // These are the types we can currently track string lengths for. | |||
730 | break; | |||
731 | ||||
732 | case MemRegion::ElementRegionKind: | |||
733 | // FIXME: Handle element regions by upper-bounding the parent region's | |||
734 | // string length. | |||
735 | return state; | |||
736 | ||||
737 | default: | |||
738 | // Other regions (mostly non-data) can't have a reliable C string length. | |||
739 | // For now, just ignore the change. | |||
740 | // FIXME: These are rare but not impossible. We should output some kind of | |||
741 | // warning for things like strcpy((char[]){'a', 0}, "b"); | |||
742 | return state; | |||
743 | } | |||
744 | ||||
745 | if (strLength.isUnknown()) | |||
746 | return state->remove<CStringLength>(MR); | |||
747 | ||||
748 | return state->set<CStringLength>(MR, strLength); | |||
749 | } | |||
750 | ||||
751 | SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C, | |||
752 | ProgramStateRef &state, | |||
753 | const Expr *Ex, | |||
754 | const MemRegion *MR, | |||
755 | bool hypothetical) { | |||
756 | if (!hypothetical) { | |||
757 | // If there's a recorded length, go ahead and return it. | |||
758 | const SVal *Recorded = state->get<CStringLength>(MR); | |||
759 | if (Recorded) | |||
760 | return *Recorded; | |||
761 | } | |||
762 | ||||
763 | // Otherwise, get a new symbol and update the state. | |||
764 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
765 | QualType sizeTy = svalBuilder.getContext().getSizeType(); | |||
766 | SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), | |||
767 | MR, Ex, sizeTy, | |||
768 | C.getLocationContext(), | |||
769 | C.blockCount()); | |||
770 | ||||
771 | if (!hypothetical) { | |||
772 | if (Optional<NonLoc> strLn = strLength.getAs<NonLoc>()) { | |||
773 | // In case of unbounded calls strlen etc bound the range to SIZE_MAX/4 | |||
774 | BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); | |||
775 | const llvm::APSInt &maxValInt = BVF.getMaxValue(sizeTy); | |||
776 | llvm::APSInt fourInt = APSIntType(maxValInt).getValue(4); | |||
777 | const llvm::APSInt *maxLengthInt = BVF.evalAPSInt(BO_Div, maxValInt, | |||
778 | fourInt); | |||
779 | NonLoc maxLength = svalBuilder.makeIntVal(*maxLengthInt); | |||
780 | SVal evalLength = svalBuilder.evalBinOpNN(state, BO_LE, *strLn, | |||
781 | maxLength, sizeTy); | |||
782 | state = state->assume(evalLength.castAs<DefinedOrUnknownSVal>(), true); | |||
783 | } | |||
784 | state = state->set<CStringLength>(MR, strLength); | |||
785 | } | |||
786 | ||||
787 | return strLength; | |||
788 | } | |||
789 | ||||
790 | SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state, | |||
791 | const Expr *Ex, SVal Buf, | |||
792 | bool hypothetical) const { | |||
793 | const MemRegion *MR = Buf.getAsRegion(); | |||
794 | if (!MR) { | |||
795 | // If we can't get a region, see if it's something we /know/ isn't a | |||
796 | // C string. In the context of locations, the only time we can issue such | |||
797 | // a warning is for labels. | |||
798 | if (Optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) { | |||
799 | if (Filter.CheckCStringNotNullTerm) { | |||
800 | SmallString<120> buf; | |||
801 | llvm::raw_svector_ostream os(buf); | |||
802 | assert(CurrentFunctionDescription)((CurrentFunctionDescription) ? static_cast<void> (0) : __assert_fail ("CurrentFunctionDescription", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 802, __PRETTY_FUNCTION__)); | |||
803 | os << "Argument to " << CurrentFunctionDescription | |||
804 | << " is the address of the label '" << Label->getLabel()->getName() | |||
805 | << "', which is not a null-terminated string"; | |||
806 | ||||
807 | emitNotCStringBug(C, state, Ex, os.str()); | |||
808 | } | |||
809 | return UndefinedVal(); | |||
810 | } | |||
811 | ||||
812 | // If it's not a region and not a label, give up. | |||
813 | return UnknownVal(); | |||
814 | } | |||
815 | ||||
816 | // If we have a region, strip casts from it and see if we can figure out | |||
817 | // its length. For anything we can't figure out, just return UnknownVal. | |||
818 | MR = MR->StripCasts(); | |||
819 | ||||
820 | switch (MR->getKind()) { | |||
821 | case MemRegion::StringRegionKind: { | |||
822 | // Modifying the contents of string regions is undefined [C99 6.4.5p6], | |||
823 | // so we can assume that the byte length is the correct C string length. | |||
824 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
825 | QualType sizeTy = svalBuilder.getContext().getSizeType(); | |||
826 | const StringLiteral *strLit = cast<StringRegion>(MR)->getStringLiteral(); | |||
827 | return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy); | |||
828 | } | |||
829 | case MemRegion::SymbolicRegionKind: | |||
830 | case MemRegion::AllocaRegionKind: | |||
831 | case MemRegion::VarRegionKind: | |||
832 | case MemRegion::FieldRegionKind: | |||
833 | case MemRegion::ObjCIvarRegionKind: | |||
834 | return getCStringLengthForRegion(C, state, Ex, MR, hypothetical); | |||
835 | case MemRegion::CompoundLiteralRegionKind: | |||
836 | // FIXME: Can we track this? Is it necessary? | |||
837 | return UnknownVal(); | |||
838 | case MemRegion::ElementRegionKind: | |||
839 | // FIXME: How can we handle this? It's not good enough to subtract the | |||
840 | // offset from the base string length; consider "123\x00567" and &a[5]. | |||
841 | return UnknownVal(); | |||
842 | default: | |||
843 | // Other regions (mostly non-data) can't have a reliable C string length. | |||
844 | // In this case, an error is emitted and UndefinedVal is returned. | |||
845 | // The caller should always be prepared to handle this case. | |||
846 | if (Filter.CheckCStringNotNullTerm) { | |||
847 | SmallString<120> buf; | |||
848 | llvm::raw_svector_ostream os(buf); | |||
849 | ||||
850 | assert
__assert_fail ("CurrentFunctionDescription", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 850, __PRETTY_FUNCTION__)); | |||
851 | os << "Argument to " << CurrentFunctionDescription << " is "; | |||
852 | ||||
853 | if (SummarizeRegion(os, C.getASTContext(), MR)) | |||
854 | os << ", which is not a null-terminated string"; | |||
855 | else | |||
856 | os << "not a null-terminated string"; | |||
857 | ||||
858 | emitNotCStringBug(C, state, Ex, os.str()); | |||
859 | } | |||
860 | return UndefinedVal(); | |||
861 | } | |||
862 | } | |||
863 | ||||
864 | const StringLiteral *CStringChecker::getCStringLiteral(CheckerContext &C, | |||
865 | ProgramStateRef &state, const Expr *expr, SVal val) const { | |||
866 | ||||
867 | // Get the memory region pointed to by the val. | |||
868 | const MemRegion *bufRegion = val.getAsRegion(); | |||
869 | if (!bufRegion) | |||
870 | return nullptr; | |||
871 | ||||
872 | // Strip casts off the memory region. | |||
873 | bufRegion = bufRegion->StripCasts(); | |||
874 | ||||
875 | // Cast the memory region to a string region. | |||
876 | const StringRegion *strRegion= dyn_cast<StringRegion>(bufRegion); | |||
877 | if (!strRegion) | |||
878 | return nullptr; | |||
879 | ||||
880 | // Return the actual string in the string region. | |||
881 | return strRegion->getStringLiteral(); | |||
882 | } | |||
883 | ||||
884 | bool CStringChecker::IsFirstBufInBound(CheckerContext &C, | |||
885 | ProgramStateRef state, | |||
886 | const Expr *FirstBuf, | |||
887 | const Expr *Size) { | |||
888 | // If we do not know that the buffer is long enough we return 'true'. | |||
889 | // Otherwise the parent region of this field region would also get | |||
890 | // invalidated, which would lead to warnings based on an unknown state. | |||
891 | ||||
892 | // Originally copied from CheckBufferAccess and CheckLocation. | |||
893 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
894 | ASTContext &Ctx = svalBuilder.getContext(); | |||
895 | const LocationContext *LCtx = C.getLocationContext(); | |||
896 | ||||
897 | QualType sizeTy = Size->getType(); | |||
898 | QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); | |||
899 | SVal BufVal = state->getSVal(FirstBuf, LCtx); | |||
900 | ||||
901 | SVal LengthVal = state->getSVal(Size, LCtx); | |||
902 | Optional<NonLoc> Length = LengthVal.getAs<NonLoc>(); | |||
903 | if (!Length) | |||
904 | return true; // cf top comment. | |||
905 | ||||
906 | // Compute the offset of the last element to be accessed: size-1. | |||
907 | NonLoc One = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>(); | |||
908 | SVal Offset = svalBuilder.evalBinOpNN(state, BO_Sub, *Length, One, sizeTy); | |||
909 | if (Offset.isUnknown()) | |||
910 | return true; // cf top comment | |||
911 | NonLoc LastOffset = Offset.castAs<NonLoc>(); | |||
912 | ||||
913 | // Check that the first buffer is sufficiently long. | |||
914 | SVal BufStart = svalBuilder.evalCast(BufVal, PtrTy, FirstBuf->getType()); | |||
915 | Optional<Loc> BufLoc = BufStart.getAs<Loc>(); | |||
916 | if (!BufLoc) | |||
917 | return true; // cf top comment. | |||
918 | ||||
919 | SVal BufEnd = | |||
920 | svalBuilder.evalBinOpLN(state, BO_Add, *BufLoc, LastOffset, PtrTy); | |||
921 | ||||
922 | // Check for out of bound array element access. | |||
923 | const MemRegion *R = BufEnd.getAsRegion(); | |||
924 | if (!R) | |||
925 | return true; // cf top comment. | |||
926 | ||||
927 | const ElementRegion *ER = dyn_cast<ElementRegion>(R); | |||
928 | if (!ER) | |||
929 | return true; // cf top comment. | |||
930 | ||||
931 | // FIXME: Does this crash when a non-standard definition | |||
932 | // of a library function is encountered? | |||
933 | assert(ER->getValueType() == C.getASTContext().CharTy &&((ER->getValueType() == C.getASTContext().CharTy && "IsFirstBufInBound should only be called with char* ElementRegions" ) ? static_cast<void> (0) : __assert_fail ("ER->getValueType() == C.getASTContext().CharTy && \"IsFirstBufInBound should only be called with char* ElementRegions\"" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 934, __PRETTY_FUNCTION__)) | |||
934 | "IsFirstBufInBound should only be called with char* ElementRegions")((ER->getValueType() == C.getASTContext().CharTy && "IsFirstBufInBound should only be called with char* ElementRegions" ) ? static_cast<void> (0) : __assert_fail ("ER->getValueType() == C.getASTContext().CharTy && \"IsFirstBufInBound should only be called with char* ElementRegions\"" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 934, __PRETTY_FUNCTION__)); | |||
935 | ||||
936 | // Get the size of the array. | |||
937 | const SubRegion *superReg = cast<SubRegion>(ER->getSuperRegion()); | |||
938 | SVal Extent = | |||
939 | svalBuilder.convertToArrayIndex(superReg->getExtent(svalBuilder)); | |||
940 | DefinedOrUnknownSVal ExtentSize = Extent.castAs<DefinedOrUnknownSVal>(); | |||
941 | ||||
942 | // Get the index of the accessed element. | |||
943 | DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>(); | |||
944 | ||||
945 | ProgramStateRef StInBound = state->assumeInBound(Idx, ExtentSize, true); | |||
946 | ||||
947 | return static_cast<bool>(StInBound); | |||
948 | } | |||
949 | ||||
950 | ProgramStateRef CStringChecker::InvalidateBuffer(CheckerContext &C, | |||
951 | ProgramStateRef state, | |||
952 | const Expr *E, SVal V, | |||
953 | bool IsSourceBuffer, | |||
954 | const Expr *Size) { | |||
955 | Optional<Loc> L = V.getAs<Loc>(); | |||
956 | if (!L) | |||
957 | return state; | |||
958 | ||||
959 | // FIXME: This is a simplified version of what's in CFRefCount.cpp -- it makes | |||
960 | // some assumptions about the value that CFRefCount can't. Even so, it should | |||
961 | // probably be refactored. | |||
962 | if (Optional<loc::MemRegionVal> MR = L->getAs<loc::MemRegionVal>()) { | |||
963 | const MemRegion *R = MR->getRegion()->StripCasts(); | |||
964 | ||||
965 | // Are we dealing with an ElementRegion? If so, we should be invalidating | |||
966 | // the super-region. | |||
967 | if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { | |||
968 | R = ER->getSuperRegion(); | |||
969 | // FIXME: What about layers of ElementRegions? | |||
970 | } | |||
971 | ||||
972 | // Invalidate this region. | |||
973 | const LocationContext *LCtx = C.getPredecessor()->getLocationContext(); | |||
974 | ||||
975 | bool CausesPointerEscape = false; | |||
976 | RegionAndSymbolInvalidationTraits ITraits; | |||
977 | // Invalidate and escape only indirect regions accessible through the source | |||
978 | // buffer. | |||
979 | if (IsSourceBuffer) { | |||
980 | ITraits.setTrait(R->getBaseRegion(), | |||
981 | RegionAndSymbolInvalidationTraits::TK_PreserveContents); | |||
982 | ITraits.setTrait(R, RegionAndSymbolInvalidationTraits::TK_SuppressEscape); | |||
983 | CausesPointerEscape = true; | |||
984 | } else { | |||
985 | const MemRegion::Kind& K = R->getKind(); | |||
986 | if (K == MemRegion::FieldRegionKind) | |||
987 | if (Size && IsFirstBufInBound(C, state, E, Size)) { | |||
988 | // If destination buffer is a field region and access is in bound, | |||
989 | // do not invalidate its super region. | |||
990 | ITraits.setTrait( | |||
991 | R, | |||
992 | RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion); | |||
993 | } | |||
994 | } | |||
995 | ||||
996 | return state->invalidateRegions(R, E, C.blockCount(), LCtx, | |||
997 | CausesPointerEscape, nullptr, nullptr, | |||
998 | &ITraits); | |||
999 | } | |||
1000 | ||||
1001 | // If we have a non-region value by chance, just remove the binding. | |||
1002 | // FIXME: is this necessary or correct? This handles the non-Region | |||
1003 | // cases. Is it ever valid to store to these? | |||
1004 | return state->killBinding(*L); | |||
1005 | } | |||
1006 | ||||
1007 | bool CStringChecker::SummarizeRegion(raw_ostream &os, ASTContext &Ctx, | |||
1008 | const MemRegion *MR) { | |||
1009 | const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); | |||
1010 | ||||
1011 | switch (MR->getKind()) { | |||
1012 | case MemRegion::FunctionCodeRegionKind: { | |||
1013 | const NamedDecl *FD = cast<FunctionCodeRegion>(MR)->getDecl(); | |||
1014 | if (FD) | |||
1015 | os << "the address of the function '" << *FD << '\''; | |||
1016 | else | |||
1017 | os << "the address of a function"; | |||
1018 | return true; | |||
1019 | } | |||
1020 | case MemRegion::BlockCodeRegionKind: | |||
1021 | os << "block text"; | |||
1022 | return true; | |||
1023 | case MemRegion::BlockDataRegionKind: | |||
1024 | os << "a block"; | |||
1025 | return true; | |||
1026 | case MemRegion::CXXThisRegionKind: | |||
1027 | case MemRegion::CXXTempObjectRegionKind: | |||
1028 | os << "a C++ temp object of type " << TVR->getValueType().getAsString(); | |||
| ||||
1029 | return true; | |||
1030 | case MemRegion::VarRegionKind: | |||
1031 | os << "a variable of type" << TVR->getValueType().getAsString(); | |||
1032 | return true; | |||
1033 | case MemRegion::FieldRegionKind: | |||
1034 | os << "a field of type " << TVR->getValueType().getAsString(); | |||
1035 | return true; | |||
1036 | case MemRegion::ObjCIvarRegionKind: | |||
1037 | os << "an instance variable of type " << TVR->getValueType().getAsString(); | |||
1038 | return true; | |||
1039 | default: | |||
1040 | return false; | |||
1041 | } | |||
1042 | } | |||
1043 | ||||
1044 | bool CStringChecker::memsetAux(const Expr *DstBuffer, SVal CharVal, | |||
1045 | const Expr *Size, CheckerContext &C, | |||
1046 | ProgramStateRef &State) { | |||
1047 | SVal MemVal = C.getSVal(DstBuffer); | |||
1048 | SVal SizeVal = C.getSVal(Size); | |||
1049 | const MemRegion *MR = MemVal.getAsRegion(); | |||
1050 | if (!MR) | |||
1051 | return false; | |||
1052 | ||||
1053 | // We're about to model memset by producing a "default binding" in the Store. | |||
1054 | // Our current implementation - RegionStore - doesn't support default bindings | |||
1055 | // that don't cover the whole base region. So we should first get the offset | |||
1056 | // and the base region to figure out whether the offset of buffer is 0. | |||
1057 | RegionOffset Offset = MR->getAsOffset(); | |||
1058 | const MemRegion *BR = Offset.getRegion(); | |||
1059 | ||||
1060 | Optional<NonLoc> SizeNL = SizeVal.getAs<NonLoc>(); | |||
1061 | if (!SizeNL) | |||
1062 | return false; | |||
1063 | ||||
1064 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
1065 | ASTContext &Ctx = C.getASTContext(); | |||
1066 | ||||
1067 | // void *memset(void *dest, int ch, size_t count); | |||
1068 | // For now we can only handle the case of offset is 0 and concrete char value. | |||
1069 | if (Offset.isValid() && !Offset.hasSymbolicOffset() && | |||
1070 | Offset.getOffset() == 0) { | |||
1071 | // Get the base region's extent. | |||
1072 | auto *SubReg = cast<SubRegion>(BR); | |||
1073 | DefinedOrUnknownSVal Extent = SubReg->getExtent(svalBuilder); | |||
1074 | ||||
1075 | ProgramStateRef StateWholeReg, StateNotWholeReg; | |||
1076 | std::tie(StateWholeReg, StateNotWholeReg) = | |||
1077 | State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL)); | |||
1078 | ||||
1079 | // With the semantic of 'memset()', we should convert the CharVal to | |||
1080 | // unsigned char. | |||
1081 | CharVal = svalBuilder.evalCast(CharVal, Ctx.UnsignedCharTy, Ctx.IntTy); | |||
1082 | ||||
1083 | ProgramStateRef StateNullChar, StateNonNullChar; | |||
1084 | std::tie(StateNullChar, StateNonNullChar) = | |||
1085 | assumeZero(C, State, CharVal, Ctx.UnsignedCharTy); | |||
1086 | ||||
1087 | if (StateWholeReg && !StateNotWholeReg && StateNullChar && | |||
1088 | !StateNonNullChar) { | |||
1089 | // If the 'memset()' acts on the whole region of destination buffer and | |||
1090 | // the value of the second argument of 'memset()' is zero, bind the second | |||
1091 | // argument's value to the destination buffer with 'default binding'. | |||
1092 | // FIXME: Since there is no perfect way to bind the non-zero character, we | |||
1093 | // can only deal with zero value here. In the future, we need to deal with | |||
1094 | // the binding of non-zero value in the case of whole region. | |||
1095 | State = State->bindDefaultZero(svalBuilder.makeLoc(BR), | |||
1096 | C.getLocationContext()); | |||
1097 | } else { | |||
1098 | // If the destination buffer's extent is not equal to the value of | |||
1099 | // third argument, just invalidate buffer. | |||
1100 | State = InvalidateBuffer(C, State, DstBuffer, MemVal, | |||
1101 | /*IsSourceBuffer*/ false, Size); | |||
1102 | } | |||
1103 | ||||
1104 | if (StateNullChar && !StateNonNullChar) { | |||
1105 | // If the value of the second argument of 'memset()' is zero, set the | |||
1106 | // string length of destination buffer to 0 directly. | |||
1107 | State = setCStringLength(State, MR, | |||
1108 | svalBuilder.makeZeroVal(Ctx.getSizeType())); | |||
1109 | } else if (!StateNullChar && StateNonNullChar) { | |||
1110 | SVal NewStrLen = svalBuilder.getMetadataSymbolVal( | |||
1111 | CStringChecker::getTag(), MR, DstBuffer, Ctx.getSizeType(), | |||
1112 | C.getLocationContext(), C.blockCount()); | |||
1113 | ||||
1114 | // If the value of second argument is not zero, then the string length | |||
1115 | // is at least the size argument. | |||
1116 | SVal NewStrLenGESize = svalBuilder.evalBinOp( | |||
1117 | State, BO_GE, NewStrLen, SizeVal, svalBuilder.getConditionType()); | |||
1118 | ||||
1119 | State = setCStringLength( | |||
1120 | State->assume(NewStrLenGESize.castAs<DefinedOrUnknownSVal>(), true), | |||
1121 | MR, NewStrLen); | |||
1122 | } | |||
1123 | } else { | |||
1124 | // If the offset is not zero and char value is not concrete, we can do | |||
1125 | // nothing but invalidate the buffer. | |||
1126 | State = InvalidateBuffer(C, State, DstBuffer, MemVal, | |||
1127 | /*IsSourceBuffer*/ false, Size); | |||
1128 | } | |||
1129 | return true; | |||
1130 | } | |||
1131 | ||||
1132 | //===----------------------------------------------------------------------===// | |||
1133 | // evaluation of individual function calls. | |||
1134 | //===----------------------------------------------------------------------===// | |||
1135 | ||||
1136 | void CStringChecker::evalCopyCommon(CheckerContext &C, | |||
1137 | const CallExpr *CE, | |||
1138 | ProgramStateRef state, | |||
1139 | const Expr *Size, const Expr *Dest, | |||
1140 | const Expr *Source, bool Restricted, | |||
1141 | bool IsMempcpy) const { | |||
1142 | CurrentFunctionDescription = "memory copy function"; | |||
1143 | ||||
1144 | // See if the size argument is zero. | |||
1145 | const LocationContext *LCtx = C.getLocationContext(); | |||
1146 | SVal sizeVal = state->getSVal(Size, LCtx); | |||
1147 | QualType sizeTy = Size->getType(); | |||
1148 | ||||
1149 | ProgramStateRef stateZeroSize, stateNonZeroSize; | |||
1150 | std::tie(stateZeroSize, stateNonZeroSize) = | |||
1151 | assumeZero(C, state, sizeVal, sizeTy); | |||
1152 | ||||
1153 | // Get the value of the Dest. | |||
1154 | SVal destVal = state->getSVal(Dest, LCtx); | |||
1155 | ||||
1156 | // If the size is zero, there won't be any actual memory access, so | |||
1157 | // just bind the return value to the destination buffer and return. | |||
1158 | if (stateZeroSize && !stateNonZeroSize) { | |||
1159 | stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal); | |||
1160 | C.addTransition(stateZeroSize); | |||
1161 | return; | |||
1162 | } | |||
1163 | ||||
1164 | // If the size can be nonzero, we have to check the other arguments. | |||
1165 | if (stateNonZeroSize) { | |||
1166 | state = stateNonZeroSize; | |||
1167 | ||||
1168 | // Ensure the destination is not null. If it is NULL there will be a | |||
1169 | // NULL pointer dereference. | |||
1170 | state = checkNonNull(C, state, Dest, destVal, 1); | |||
1171 | if (!state) | |||
1172 | return; | |||
1173 | ||||
1174 | // Get the value of the Src. | |||
1175 | SVal srcVal = state->getSVal(Source, LCtx); | |||
1176 | ||||
1177 | // Ensure the source is not null. If it is NULL there will be a | |||
1178 | // NULL pointer dereference. | |||
1179 | state = checkNonNull(C, state, Source, srcVal, 2); | |||
1180 | if (!state) | |||
1181 | return; | |||
1182 | ||||
1183 | // Ensure the accesses are valid and that the buffers do not overlap. | |||
1184 | const char * const writeWarning = | |||
1185 | "Memory copy function overflows destination buffer"; | |||
1186 | state = CheckBufferAccess(C, state, Size, Dest, Source, | |||
1187 | writeWarning, /* sourceWarning = */ nullptr); | |||
1188 | if (Restricted) | |||
1189 | state = CheckOverlap(C, state, Size, Dest, Source); | |||
1190 | ||||
1191 | if (!state) | |||
1192 | return; | |||
1193 | ||||
1194 | // If this is mempcpy, get the byte after the last byte copied and | |||
1195 | // bind the expr. | |||
1196 | if (IsMempcpy) { | |||
1197 | // Get the byte after the last byte copied. | |||
1198 | SValBuilder &SvalBuilder = C.getSValBuilder(); | |||
1199 | ASTContext &Ctx = SvalBuilder.getContext(); | |||
1200 | QualType CharPtrTy = Ctx.getPointerType(Ctx.CharTy); | |||
1201 | SVal DestRegCharVal = | |||
1202 | SvalBuilder.evalCast(destVal, CharPtrTy, Dest->getType()); | |||
1203 | SVal lastElement = C.getSValBuilder().evalBinOp( | |||
1204 | state, BO_Add, DestRegCharVal, sizeVal, Dest->getType()); | |||
1205 | // If we don't know how much we copied, we can at least | |||
1206 | // conjure a return value for later. | |||
1207 | if (lastElement.isUnknown()) | |||
1208 | lastElement = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, | |||
1209 | C.blockCount()); | |||
1210 | ||||
1211 | // The byte after the last byte copied is the return value. | |||
1212 | state = state->BindExpr(CE, LCtx, lastElement); | |||
1213 | } else { | |||
1214 | // All other copies return the destination buffer. | |||
1215 | // (Well, bcopy() has a void return type, but this won't hurt.) | |||
1216 | state = state->BindExpr(CE, LCtx, destVal); | |||
1217 | } | |||
1218 | ||||
1219 | // Invalidate the destination (regular invalidation without pointer-escaping | |||
1220 | // the address of the top-level region). | |||
1221 | // FIXME: Even if we can't perfectly model the copy, we should see if we | |||
1222 | // can use LazyCompoundVals to copy the source values into the destination. | |||
1223 | // This would probably remove any existing bindings past the end of the | |||
1224 | // copied region, but that's still an improvement over blank invalidation. | |||
1225 | state = InvalidateBuffer(C, state, Dest, C.getSVal(Dest), | |||
1226 | /*IsSourceBuffer*/false, Size); | |||
1227 | ||||
1228 | // Invalidate the source (const-invalidation without const-pointer-escaping | |||
1229 | // the address of the top-level region). | |||
1230 | state = InvalidateBuffer(C, state, Source, C.getSVal(Source), | |||
1231 | /*IsSourceBuffer*/true, nullptr); | |||
1232 | ||||
1233 | C.addTransition(state); | |||
1234 | } | |||
1235 | } | |||
1236 | ||||
1237 | ||||
1238 | void CStringChecker::evalMemcpy(CheckerContext &C, const CallExpr *CE) const { | |||
1239 | // void *memcpy(void *restrict dst, const void *restrict src, size_t n); | |||
1240 | // The return value is the address of the destination buffer. | |||
1241 | const Expr *Dest = CE->getArg(0); | |||
1242 | ProgramStateRef state = C.getState(); | |||
1243 | ||||
1244 | evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true); | |||
1245 | } | |||
1246 | ||||
1247 | void CStringChecker::evalMempcpy(CheckerContext &C, const CallExpr *CE) const { | |||
1248 | // void *mempcpy(void *restrict dst, const void *restrict src, size_t n); | |||
1249 | // The return value is a pointer to the byte following the last written byte. | |||
1250 | const Expr *Dest = CE->getArg(0); | |||
1251 | ProgramStateRef state = C.getState(); | |||
1252 | ||||
1253 | evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1), true, true); | |||
1254 | } | |||
1255 | ||||
1256 | void CStringChecker::evalMemmove(CheckerContext &C, const CallExpr *CE) const { | |||
1257 | // void *memmove(void *dst, const void *src, size_t n); | |||
1258 | // The return value is the address of the destination buffer. | |||
1259 | const Expr *Dest = CE->getArg(0); | |||
1260 | ProgramStateRef state = C.getState(); | |||
1261 | ||||
1262 | evalCopyCommon(C, CE, state, CE->getArg(2), Dest, CE->getArg(1)); | |||
1263 | } | |||
1264 | ||||
1265 | void CStringChecker::evalBcopy(CheckerContext &C, const CallExpr *CE) const { | |||
1266 | // void bcopy(const void *src, void *dst, size_t n); | |||
1267 | evalCopyCommon(C, CE, C.getState(), | |||
1268 | CE->getArg(2), CE->getArg(1), CE->getArg(0)); | |||
1269 | } | |||
1270 | ||||
1271 | void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { | |||
1272 | // int memcmp(const void *s1, const void *s2, size_t n); | |||
1273 | CurrentFunctionDescription = "memory comparison function"; | |||
1274 | ||||
1275 | const Expr *Left = CE->getArg(0); | |||
1276 | const Expr *Right = CE->getArg(1); | |||
1277 | const Expr *Size = CE->getArg(2); | |||
1278 | ||||
1279 | ProgramStateRef state = C.getState(); | |||
1280 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
1281 | ||||
1282 | // See if the size argument is zero. | |||
1283 | const LocationContext *LCtx = C.getLocationContext(); | |||
1284 | SVal sizeVal = state->getSVal(Size, LCtx); | |||
1285 | QualType sizeTy = Size->getType(); | |||
1286 | ||||
1287 | ProgramStateRef stateZeroSize, stateNonZeroSize; | |||
1288 | std::tie(stateZeroSize, stateNonZeroSize) = | |||
1289 | assumeZero(C, state, sizeVal, sizeTy); | |||
1290 | ||||
1291 | // If the size can be zero, the result will be 0 in that case, and we don't | |||
1292 | // have to check either of the buffers. | |||
1293 | if (stateZeroSize) { | |||
1294 | state = stateZeroSize; | |||
1295 | state = state->BindExpr(CE, LCtx, | |||
1296 | svalBuilder.makeZeroVal(CE->getType())); | |||
1297 | C.addTransition(state); | |||
1298 | } | |||
1299 | ||||
1300 | // If the size can be nonzero, we have to check the other arguments. | |||
1301 | if (stateNonZeroSize) { | |||
1302 | state = stateNonZeroSize; | |||
1303 | // If we know the two buffers are the same, we know the result is 0. | |||
1304 | // First, get the two buffers' addresses. Another checker will have already | |||
1305 | // made sure they're not undefined. | |||
1306 | DefinedOrUnknownSVal LV = | |||
1307 | state->getSVal(Left, LCtx).castAs<DefinedOrUnknownSVal>(); | |||
1308 | DefinedOrUnknownSVal RV = | |||
1309 | state->getSVal(Right, LCtx).castAs<DefinedOrUnknownSVal>(); | |||
1310 | ||||
1311 | // See if they are the same. | |||
1312 | DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); | |||
1313 | ProgramStateRef StSameBuf, StNotSameBuf; | |||
1314 | std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); | |||
1315 | ||||
1316 | // If the two arguments are the same buffer, we know the result is 0, | |||
1317 | // and we only need to check one size. | |||
1318 | if (StSameBuf && !StNotSameBuf) { | |||
1319 | state = StSameBuf; | |||
1320 | state = CheckBufferAccess(C, state, Size, Left); | |||
1321 | if (state) { | |||
1322 | state = StSameBuf->BindExpr(CE, LCtx, | |||
1323 | svalBuilder.makeZeroVal(CE->getType())); | |||
1324 | C.addTransition(state); | |||
1325 | } | |||
1326 | return; | |||
1327 | } | |||
1328 | ||||
1329 | // If the two arguments might be different buffers, we have to check | |||
1330 | // the size of both of them. | |||
1331 | assert(StNotSameBuf)((StNotSameBuf) ? static_cast<void> (0) : __assert_fail ("StNotSameBuf", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1331, __PRETTY_FUNCTION__)); | |||
1332 | state = CheckBufferAccess(C, state, Size, Left, Right); | |||
1333 | if (state) { | |||
1334 | // The return value is the comparison result, which we don't know. | |||
1335 | SVal CmpV = | |||
1336 | svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); | |||
1337 | state = state->BindExpr(CE, LCtx, CmpV); | |||
1338 | C.addTransition(state); | |||
1339 | } | |||
1340 | } | |||
1341 | } | |||
1342 | ||||
1343 | void CStringChecker::evalstrLength(CheckerContext &C, | |||
1344 | const CallExpr *CE) const { | |||
1345 | // size_t strlen(const char *s); | |||
1346 | evalstrLengthCommon(C, CE, /* IsStrnlen = */ false); | |||
1347 | } | |||
1348 | ||||
1349 | void CStringChecker::evalstrnLength(CheckerContext &C, | |||
1350 | const CallExpr *CE) const { | |||
1351 | // size_t strnlen(const char *s, size_t maxlen); | |||
1352 | evalstrLengthCommon(C, CE, /* IsStrnlen = */ true); | |||
1353 | } | |||
1354 | ||||
1355 | void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, | |||
1356 | bool IsStrnlen) const { | |||
1357 | CurrentFunctionDescription = "string length function"; | |||
1358 | ProgramStateRef state = C.getState(); | |||
1359 | const LocationContext *LCtx = C.getLocationContext(); | |||
1360 | ||||
1361 | if (IsStrnlen) { | |||
1362 | const Expr *maxlenExpr = CE->getArg(1); | |||
1363 | SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); | |||
1364 | ||||
1365 | ProgramStateRef stateZeroSize, stateNonZeroSize; | |||
1366 | std::tie(stateZeroSize, stateNonZeroSize) = | |||
1367 | assumeZero(C, state, maxlenVal, maxlenExpr->getType()); | |||
1368 | ||||
1369 | // If the size can be zero, the result will be 0 in that case, and we don't | |||
1370 | // have to check the string itself. | |||
1371 | if (stateZeroSize) { | |||
1372 | SVal zero = C.getSValBuilder().makeZeroVal(CE->getType()); | |||
1373 | stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero); | |||
1374 | C.addTransition(stateZeroSize); | |||
1375 | } | |||
1376 | ||||
1377 | // If the size is GUARANTEED to be zero, we're done! | |||
1378 | if (!stateNonZeroSize) | |||
1379 | return; | |||
1380 | ||||
1381 | // Otherwise, record the assumption that the size is nonzero. | |||
1382 | state = stateNonZeroSize; | |||
1383 | } | |||
1384 | ||||
1385 | // Check that the string argument is non-null. | |||
1386 | const Expr *Arg = CE->getArg(0); | |||
1387 | SVal ArgVal = state->getSVal(Arg, LCtx); | |||
1388 | ||||
1389 | state = checkNonNull(C, state, Arg, ArgVal, 1); | |||
1390 | ||||
1391 | if (!state) | |||
1392 | return; | |||
1393 | ||||
1394 | SVal strLength = getCStringLength(C, state, Arg, ArgVal); | |||
1395 | ||||
1396 | // If the argument isn't a valid C string, there's no valid state to | |||
1397 | // transition to. | |||
1398 | if (strLength.isUndef()) | |||
1399 | return; | |||
1400 | ||||
1401 | DefinedOrUnknownSVal result = UnknownVal(); | |||
1402 | ||||
1403 | // If the check is for strnlen() then bind the return value to no more than | |||
1404 | // the maxlen value. | |||
1405 | if (IsStrnlen) { | |||
1406 | QualType cmpTy = C.getSValBuilder().getConditionType(); | |||
1407 | ||||
1408 | // It's a little unfortunate to be getting this again, | |||
1409 | // but it's not that expensive... | |||
1410 | const Expr *maxlenExpr = CE->getArg(1); | |||
1411 | SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); | |||
1412 | ||||
1413 | Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>(); | |||
1414 | Optional<NonLoc> maxlenValNL = maxlenVal.getAs<NonLoc>(); | |||
1415 | ||||
1416 | if (strLengthNL && maxlenValNL) { | |||
1417 | ProgramStateRef stateStringTooLong, stateStringNotTooLong; | |||
1418 | ||||
1419 | // Check if the strLength is greater than the maxlen. | |||
1420 | std::tie(stateStringTooLong, stateStringNotTooLong) = state->assume( | |||
1421 | C.getSValBuilder() | |||
1422 | .evalBinOpNN(state, BO_GT, *strLengthNL, *maxlenValNL, cmpTy) | |||
1423 | .castAs<DefinedOrUnknownSVal>()); | |||
1424 | ||||
1425 | if (stateStringTooLong && !stateStringNotTooLong) { | |||
1426 | // If the string is longer than maxlen, return maxlen. | |||
1427 | result = *maxlenValNL; | |||
1428 | } else if (stateStringNotTooLong && !stateStringTooLong) { | |||
1429 | // If the string is shorter than maxlen, return its length. | |||
1430 | result = *strLengthNL; | |||
1431 | } | |||
1432 | } | |||
1433 | ||||
1434 | if (result.isUnknown()) { | |||
1435 | // If we don't have enough information for a comparison, there's | |||
1436 | // no guarantee the full string length will actually be returned. | |||
1437 | // All we know is the return value is the min of the string length | |||
1438 | // and the limit. This is better than nothing. | |||
1439 | result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, | |||
1440 | C.blockCount()); | |||
1441 | NonLoc resultNL = result.castAs<NonLoc>(); | |||
1442 | ||||
1443 | if (strLengthNL) { | |||
1444 | state = state->assume(C.getSValBuilder().evalBinOpNN( | |||
1445 | state, BO_LE, resultNL, *strLengthNL, cmpTy) | |||
1446 | .castAs<DefinedOrUnknownSVal>(), true); | |||
1447 | } | |||
1448 | ||||
1449 | if (maxlenValNL) { | |||
1450 | state = state->assume(C.getSValBuilder().evalBinOpNN( | |||
1451 | state, BO_LE, resultNL, *maxlenValNL, cmpTy) | |||
1452 | .castAs<DefinedOrUnknownSVal>(), true); | |||
1453 | } | |||
1454 | } | |||
1455 | ||||
1456 | } else { | |||
1457 | // This is a plain strlen(), not strnlen(). | |||
1458 | result = strLength.castAs<DefinedOrUnknownSVal>(); | |||
1459 | ||||
1460 | // If we don't know the length of the string, conjure a return | |||
1461 | // value, so it can be used in constraints, at least. | |||
1462 | if (result.isUnknown()) { | |||
1463 | result = C.getSValBuilder().conjureSymbolVal(nullptr, CE, LCtx, | |||
1464 | C.blockCount()); | |||
1465 | } | |||
1466 | } | |||
1467 | ||||
1468 | // Bind the return value. | |||
1469 | assert(!result.isUnknown() && "Should have conjured a value by now")((!result.isUnknown() && "Should have conjured a value by now" ) ? static_cast<void> (0) : __assert_fail ("!result.isUnknown() && \"Should have conjured a value by now\"" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1469, __PRETTY_FUNCTION__)); | |||
1470 | state = state->BindExpr(CE, LCtx, result); | |||
1471 | C.addTransition(state); | |||
1472 | } | |||
1473 | ||||
1474 | void CStringChecker::evalStrcpy(CheckerContext &C, const CallExpr *CE) const { | |||
1475 | // char *strcpy(char *restrict dst, const char *restrict src); | |||
1476 | evalStrcpyCommon(C, CE, | |||
1477 | /* ReturnEnd = */ false, | |||
1478 | /* IsBounded = */ false, | |||
1479 | /* appendK = */ ConcatFnKind::none); | |||
1480 | } | |||
1481 | ||||
1482 | void CStringChecker::evalStrncpy(CheckerContext &C, const CallExpr *CE) const { | |||
1483 | // char *strncpy(char *restrict dst, const char *restrict src, size_t n); | |||
1484 | evalStrcpyCommon(C, CE, | |||
1485 | /* ReturnEnd = */ false, | |||
1486 | /* IsBounded = */ true, | |||
1487 | /* appendK = */ ConcatFnKind::none); | |||
1488 | } | |||
1489 | ||||
1490 | void CStringChecker::evalStpcpy(CheckerContext &C, const CallExpr *CE) const { | |||
1491 | // char *stpcpy(char *restrict dst, const char *restrict src); | |||
1492 | evalStrcpyCommon(C, CE, | |||
1493 | /* ReturnEnd = */ true, | |||
1494 | /* IsBounded = */ false, | |||
1495 | /* appendK = */ ConcatFnKind::none); | |||
1496 | } | |||
1497 | ||||
1498 | void CStringChecker::evalStrlcpy(CheckerContext &C, const CallExpr *CE) const { | |||
1499 | // size_t strlcpy(char *dest, const char *src, size_t size); | |||
1500 | evalStrcpyCommon(C, CE, | |||
1501 | /* ReturnEnd = */ true, | |||
1502 | /* IsBounded = */ true, | |||
1503 | /* appendK = */ ConcatFnKind::none, | |||
1504 | /* returnPtr = */ false); | |||
1505 | } | |||
1506 | ||||
1507 | void CStringChecker::evalStrcat(CheckerContext &C, const CallExpr *CE) const { | |||
1508 | // char *strcat(char *restrict s1, const char *restrict s2); | |||
1509 | evalStrcpyCommon(C, CE, | |||
1510 | /* ReturnEnd = */ false, | |||
1511 | /* IsBounded = */ false, | |||
1512 | /* appendK = */ ConcatFnKind::strcat); | |||
1513 | } | |||
1514 | ||||
1515 | void CStringChecker::evalStrncat(CheckerContext &C, const CallExpr *CE) const { | |||
1516 | //char *strncat(char *restrict s1, const char *restrict s2, size_t n); | |||
1517 | evalStrcpyCommon(C, CE, | |||
1518 | /* ReturnEnd = */ false, | |||
1519 | /* IsBounded = */ true, | |||
1520 | /* appendK = */ ConcatFnKind::strcat); | |||
1521 | } | |||
1522 | ||||
1523 | void CStringChecker::evalStrlcat(CheckerContext &C, const CallExpr *CE) const { | |||
1524 | // size_t strlcat(char *dst, const char *src, size_t size); | |||
1525 | // It will append at most size - strlen(dst) - 1 bytes, | |||
1526 | // NULL-terminating the result. | |||
1527 | evalStrcpyCommon(C, CE, | |||
1528 | /* ReturnEnd = */ false, | |||
1529 | /* IsBounded = */ true, | |||
1530 | /* appendK = */ ConcatFnKind::strlcat, | |||
1531 | /* returnPtr = */ false); | |||
1532 | } | |||
1533 | ||||
1534 | void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, | |||
1535 | bool ReturnEnd, bool IsBounded, | |||
1536 | ConcatFnKind appendK, | |||
1537 | bool returnPtr) const { | |||
1538 | if (appendK == ConcatFnKind::none) | |||
1539 | CurrentFunctionDescription = "string copy function"; | |||
1540 | else | |||
1541 | CurrentFunctionDescription = "string concatenation function"; | |||
1542 | ProgramStateRef state = C.getState(); | |||
1543 | const LocationContext *LCtx = C.getLocationContext(); | |||
1544 | ||||
1545 | // Check that the destination is non-null. | |||
1546 | const Expr *Dst = CE->getArg(0); | |||
1547 | SVal DstVal = state->getSVal(Dst, LCtx); | |||
1548 | ||||
1549 | state = checkNonNull(C, state, Dst, DstVal, 1); | |||
1550 | if (!state) | |||
1551 | return; | |||
1552 | ||||
1553 | // Check that the source is non-null. | |||
1554 | const Expr *srcExpr = CE->getArg(1); | |||
1555 | SVal srcVal = state->getSVal(srcExpr, LCtx); | |||
1556 | state = checkNonNull(C, state, srcExpr, srcVal, 2); | |||
1557 | if (!state) | |||
1558 | return; | |||
1559 | ||||
1560 | // Get the string length of the source. | |||
1561 | SVal strLength = getCStringLength(C, state, srcExpr, srcVal); | |||
1562 | Optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>(); | |||
1563 | ||||
1564 | // Get the string length of the destination buffer. | |||
1565 | SVal dstStrLength = getCStringLength(C, state, Dst, DstVal); | |||
1566 | Optional<NonLoc> dstStrLengthNL = dstStrLength.getAs<NonLoc>(); | |||
1567 | ||||
1568 | // If the source isn't a valid C string, give up. | |||
1569 | if (strLength.isUndef()) | |||
1570 | return; | |||
1571 | ||||
1572 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
1573 | QualType cmpTy = svalBuilder.getConditionType(); | |||
1574 | QualType sizeTy = svalBuilder.getContext().getSizeType(); | |||
1575 | ||||
1576 | // These two values allow checking two kinds of errors: | |||
1577 | // - actual overflows caused by a source that doesn't fit in the destination | |||
1578 | // - potential overflows caused by a bound that could exceed the destination | |||
1579 | SVal amountCopied = UnknownVal(); | |||
1580 | SVal maxLastElementIndex = UnknownVal(); | |||
1581 | const char *boundWarning = nullptr; | |||
1582 | ||||
1583 | state = CheckOverlap(C, state, IsBounded ? CE->getArg(2) : CE->getArg(1), Dst, | |||
1584 | srcExpr); | |||
1585 | ||||
1586 | if (!state) | |||
1587 | return; | |||
1588 | ||||
1589 | // If the function is strncpy, strncat, etc... it is bounded. | |||
1590 | if (IsBounded) { | |||
1591 | // Get the max number of characters to copy. | |||
1592 | const Expr *lenExpr = CE->getArg(2); | |||
1593 | SVal lenVal = state->getSVal(lenExpr, LCtx); | |||
1594 | ||||
1595 | // Protect against misdeclared strncpy(). | |||
1596 | lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType()); | |||
1597 | ||||
1598 | Optional<NonLoc> lenValNL = lenVal.getAs<NonLoc>(); | |||
1599 | ||||
1600 | // If we know both values, we might be able to figure out how much | |||
1601 | // we're copying. | |||
1602 | if (strLengthNL && lenValNL) { | |||
1603 | switch (appendK) { | |||
1604 | case ConcatFnKind::none: | |||
1605 | case ConcatFnKind::strcat: { | |||
1606 | ProgramStateRef stateSourceTooLong, stateSourceNotTooLong; | |||
1607 | // Check if the max number to copy is less than the length of the src. | |||
1608 | // If the bound is equal to the source length, strncpy won't null- | |||
1609 | // terminate the result! | |||
1610 | std::tie(stateSourceTooLong, stateSourceNotTooLong) = state->assume( | |||
1611 | svalBuilder | |||
1612 | .evalBinOpNN(state, BO_GE, *strLengthNL, *lenValNL, cmpTy) | |||
1613 | .castAs<DefinedOrUnknownSVal>()); | |||
1614 | ||||
1615 | if (stateSourceTooLong && !stateSourceNotTooLong) { | |||
1616 | // Max number to copy is less than the length of the src, so the | |||
1617 | // actual strLength copied is the max number arg. | |||
1618 | state = stateSourceTooLong; | |||
1619 | amountCopied = lenVal; | |||
1620 | ||||
1621 | } else if (!stateSourceTooLong && stateSourceNotTooLong) { | |||
1622 | // The source buffer entirely fits in the bound. | |||
1623 | state = stateSourceNotTooLong; | |||
1624 | amountCopied = strLength; | |||
1625 | } | |||
1626 | break; | |||
1627 | } | |||
1628 | case ConcatFnKind::strlcat: | |||
1629 | if (!dstStrLengthNL) | |||
1630 | return; | |||
1631 | ||||
1632 | // amountCopied = min (size - dstLen - 1 , srcLen) | |||
1633 | SVal freeSpace = svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, | |||
1634 | *dstStrLengthNL, sizeTy); | |||
1635 | if (!freeSpace.getAs<NonLoc>()) | |||
1636 | return; | |||
1637 | freeSpace = | |||
1638 | svalBuilder.evalBinOp(state, BO_Sub, freeSpace, | |||
1639 | svalBuilder.makeIntVal(1, sizeTy), sizeTy); | |||
1640 | Optional<NonLoc> freeSpaceNL = freeSpace.getAs<NonLoc>(); | |||
1641 | ||||
1642 | // While unlikely, it is possible that the subtraction is | |||
1643 | // too complex to compute, let's check whether it succeeded. | |||
1644 | if (!freeSpaceNL) | |||
1645 | return; | |||
1646 | SVal hasEnoughSpace = svalBuilder.evalBinOpNN( | |||
1647 | state, BO_LE, *strLengthNL, *freeSpaceNL, cmpTy); | |||
1648 | ||||
1649 | ProgramStateRef TrueState, FalseState; | |||
1650 | std::tie(TrueState, FalseState) = | |||
1651 | state->assume(hasEnoughSpace.castAs<DefinedOrUnknownSVal>()); | |||
1652 | ||||
1653 | // srcStrLength <= size - dstStrLength -1 | |||
1654 | if (TrueState && !FalseState) { | |||
1655 | amountCopied = strLength; | |||
1656 | } | |||
1657 | ||||
1658 | // srcStrLength > size - dstStrLength -1 | |||
1659 | if (!TrueState && FalseState) { | |||
1660 | amountCopied = freeSpace; | |||
1661 | } | |||
1662 | ||||
1663 | if (TrueState && FalseState) | |||
1664 | amountCopied = UnknownVal(); | |||
1665 | break; | |||
1666 | } | |||
1667 | } | |||
1668 | // We still want to know if the bound is known to be too large. | |||
1669 | if (lenValNL) { | |||
1670 | switch (appendK) { | |||
1671 | case ConcatFnKind::strcat: | |||
1672 | // For strncat, the check is strlen(dst) + lenVal < sizeof(dst) | |||
1673 | ||||
1674 | // Get the string length of the destination. If the destination is | |||
1675 | // memory that can't have a string length, we shouldn't be copying | |||
1676 | // into it anyway. | |||
1677 | if (dstStrLength.isUndef()) | |||
1678 | return; | |||
1679 | ||||
1680 | if (dstStrLengthNL) { | |||
1681 | maxLastElementIndex = svalBuilder.evalBinOpNN( | |||
1682 | state, BO_Add, *lenValNL, *dstStrLengthNL, sizeTy); | |||
1683 | ||||
1684 | boundWarning = "Size argument is greater than the free space in the " | |||
1685 | "destination buffer"; | |||
1686 | } | |||
1687 | break; | |||
1688 | case ConcatFnKind::none: | |||
1689 | case ConcatFnKind::strlcat: | |||
1690 | // For strncpy and strlcat, this is just checking | |||
1691 | // that lenVal <= sizeof(dst). | |||
1692 | // (Yes, strncpy and strncat differ in how they treat termination. | |||
1693 | // strncat ALWAYS terminates, but strncpy doesn't.) | |||
1694 | ||||
1695 | // We need a special case for when the copy size is zero, in which | |||
1696 | // case strncpy will do no work at all. Our bounds check uses n-1 | |||
1697 | // as the last element accessed, so n == 0 is problematic. | |||
1698 | ProgramStateRef StateZeroSize, StateNonZeroSize; | |||
1699 | std::tie(StateZeroSize, StateNonZeroSize) = | |||
1700 | assumeZero(C, state, *lenValNL, sizeTy); | |||
1701 | ||||
1702 | // If the size is known to be zero, we're done. | |||
1703 | if (StateZeroSize && !StateNonZeroSize) { | |||
1704 | if (returnPtr) { | |||
1705 | StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, DstVal); | |||
1706 | } else { | |||
1707 | if (appendK == ConcatFnKind::none) { | |||
1708 | // strlcpy returns strlen(src) | |||
1709 | StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, strLength); | |||
1710 | } else { | |||
1711 | // strlcat returns strlen(src) + strlen(dst) | |||
1712 | SVal retSize = svalBuilder.evalBinOp( | |||
1713 | state, BO_Add, strLength, dstStrLength, sizeTy); | |||
1714 | StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, retSize); | |||
1715 | } | |||
1716 | } | |||
1717 | C.addTransition(StateZeroSize); | |||
1718 | return; | |||
1719 | } | |||
1720 | ||||
1721 | // Otherwise, go ahead and figure out the last element we'll touch. | |||
1722 | // We don't record the non-zero assumption here because we can't | |||
1723 | // be sure. We won't warn on a possible zero. | |||
1724 | NonLoc one = svalBuilder.makeIntVal(1, sizeTy).castAs<NonLoc>(); | |||
1725 | maxLastElementIndex = | |||
1726 | svalBuilder.evalBinOpNN(state, BO_Sub, *lenValNL, one, sizeTy); | |||
1727 | boundWarning = "Size argument is greater than the length of the " | |||
1728 | "destination buffer"; | |||
1729 | break; | |||
1730 | } | |||
1731 | } | |||
1732 | } else { | |||
1733 | // The function isn't bounded. The amount copied should match the length | |||
1734 | // of the source buffer. | |||
1735 | amountCopied = strLength; | |||
1736 | } | |||
1737 | ||||
1738 | assert(state)((state) ? static_cast<void> (0) : __assert_fail ("state" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1738, __PRETTY_FUNCTION__)); | |||
1739 | ||||
1740 | // This represents the number of characters copied into the destination | |||
1741 | // buffer. (It may not actually be the strlen if the destination buffer | |||
1742 | // is not terminated.) | |||
1743 | SVal finalStrLength = UnknownVal(); | |||
1744 | SVal strlRetVal = UnknownVal(); | |||
1745 | ||||
1746 | if (appendK == ConcatFnKind::none && !returnPtr) { | |||
1747 | // strlcpy returns the sizeof(src) | |||
1748 | strlRetVal = strLength; | |||
1749 | } | |||
1750 | ||||
1751 | // If this is an appending function (strcat, strncat...) then set the | |||
1752 | // string length to strlen(src) + strlen(dst) since the buffer will | |||
1753 | // ultimately contain both. | |||
1754 | if (appendK != ConcatFnKind::none) { | |||
1755 | // Get the string length of the destination. If the destination is memory | |||
1756 | // that can't have a string length, we shouldn't be copying into it anyway. | |||
1757 | if (dstStrLength.isUndef()) | |||
1758 | return; | |||
1759 | ||||
1760 | if (appendK == ConcatFnKind::strlcat && dstStrLengthNL && strLengthNL) { | |||
1761 | strlRetVal = svalBuilder.evalBinOpNN(state, BO_Add, *strLengthNL, | |||
1762 | *dstStrLengthNL, sizeTy); | |||
1763 | } | |||
1764 | ||||
1765 | Optional<NonLoc> amountCopiedNL = amountCopied.getAs<NonLoc>(); | |||
1766 | ||||
1767 | // If we know both string lengths, we might know the final string length. | |||
1768 | if (amountCopiedNL && dstStrLengthNL) { | |||
1769 | // Make sure the two lengths together don't overflow a size_t. | |||
1770 | state = checkAdditionOverflow(C, state, *amountCopiedNL, *dstStrLengthNL); | |||
1771 | if (!state) | |||
1772 | return; | |||
1773 | ||||
1774 | finalStrLength = svalBuilder.evalBinOpNN(state, BO_Add, *amountCopiedNL, | |||
1775 | *dstStrLengthNL, sizeTy); | |||
1776 | } | |||
1777 | ||||
1778 | // If we couldn't get a single value for the final string length, | |||
1779 | // we can at least bound it by the individual lengths. | |||
1780 | if (finalStrLength.isUnknown()) { | |||
1781 | // Try to get a "hypothetical" string length symbol, which we can later | |||
1782 | // set as a real value if that turns out to be the case. | |||
1783 | finalStrLength = getCStringLength(C, state, CE, DstVal, true); | |||
1784 | assert(!finalStrLength.isUndef())((!finalStrLength.isUndef()) ? static_cast<void> (0) : __assert_fail ("!finalStrLength.isUndef()", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1784, __PRETTY_FUNCTION__)); | |||
1785 | ||||
1786 | if (Optional<NonLoc> finalStrLengthNL = finalStrLength.getAs<NonLoc>()) { | |||
1787 | if (amountCopiedNL && appendK == ConcatFnKind::none) { | |||
1788 | // we overwrite dst string with the src | |||
1789 | // finalStrLength >= srcStrLength | |||
1790 | SVal sourceInResult = svalBuilder.evalBinOpNN( | |||
1791 | state, BO_GE, *finalStrLengthNL, *amountCopiedNL, cmpTy); | |||
1792 | state = state->assume(sourceInResult.castAs<DefinedOrUnknownSVal>(), | |||
1793 | true); | |||
1794 | if (!state) | |||
1795 | return; | |||
1796 | } | |||
1797 | ||||
1798 | if (dstStrLengthNL && appendK != ConcatFnKind::none) { | |||
1799 | // we extend the dst string with the src | |||
1800 | // finalStrLength >= dstStrLength | |||
1801 | SVal destInResult = svalBuilder.evalBinOpNN(state, BO_GE, | |||
1802 | *finalStrLengthNL, | |||
1803 | *dstStrLengthNL, | |||
1804 | cmpTy); | |||
1805 | state = | |||
1806 | state->assume(destInResult.castAs<DefinedOrUnknownSVal>(), true); | |||
1807 | if (!state) | |||
1808 | return; | |||
1809 | } | |||
1810 | } | |||
1811 | } | |||
1812 | ||||
1813 | } else { | |||
1814 | // Otherwise, this is a copy-over function (strcpy, strncpy, ...), and | |||
1815 | // the final string length will match the input string length. | |||
1816 | finalStrLength = amountCopied; | |||
1817 | } | |||
1818 | ||||
1819 | SVal Result; | |||
1820 | ||||
1821 | if (returnPtr) { | |||
1822 | // The final result of the function will either be a pointer past the last | |||
1823 | // copied element, or a pointer to the start of the destination buffer. | |||
1824 | Result = (ReturnEnd ? UnknownVal() : DstVal); | |||
1825 | } else { | |||
1826 | if (appendK == ConcatFnKind::strlcat || appendK == ConcatFnKind::none) | |||
1827 | //strlcpy, strlcat | |||
1828 | Result = strlRetVal; | |||
1829 | else | |||
1830 | Result = finalStrLength; | |||
1831 | } | |||
1832 | ||||
1833 | assert(state)((state) ? static_cast<void> (0) : __assert_fail ("state" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1833, __PRETTY_FUNCTION__)); | |||
1834 | ||||
1835 | // If the destination is a MemRegion, try to check for a buffer overflow and | |||
1836 | // record the new string length. | |||
1837 | if (Optional<loc::MemRegionVal> dstRegVal = | |||
1838 | DstVal.getAs<loc::MemRegionVal>()) { | |||
1839 | QualType ptrTy = Dst->getType(); | |||
1840 | ||||
1841 | // If we have an exact value on a bounded copy, use that to check for | |||
1842 | // overflows, rather than our estimate about how much is actually copied. | |||
1843 | if (boundWarning) { | |||
1844 | if (Optional<NonLoc> maxLastNL = maxLastElementIndex.getAs<NonLoc>()) { | |||
1845 | SVal maxLastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, | |||
1846 | *maxLastNL, ptrTy); | |||
1847 | state = CheckLocation(C, state, CE->getArg(2), maxLastElement, | |||
1848 | boundWarning); | |||
1849 | if (!state) | |||
1850 | return; | |||
1851 | } | |||
1852 | } | |||
1853 | ||||
1854 | // Then, if the final length is known... | |||
1855 | if (Optional<NonLoc> knownStrLength = finalStrLength.getAs<NonLoc>()) { | |||
1856 | SVal lastElement = svalBuilder.evalBinOpLN(state, BO_Add, *dstRegVal, | |||
1857 | *knownStrLength, ptrTy); | |||
1858 | ||||
1859 | // ...and we haven't checked the bound, we'll check the actual copy. | |||
1860 | if (!boundWarning) { | |||
1861 | const char * const warningMsg = | |||
1862 | "String copy function overflows destination buffer"; | |||
1863 | state = CheckLocation(C, state, Dst, lastElement, warningMsg); | |||
1864 | if (!state) | |||
1865 | return; | |||
1866 | } | |||
1867 | ||||
1868 | // If this is a stpcpy-style copy, the last element is the return value. | |||
1869 | if (returnPtr && ReturnEnd) | |||
1870 | Result = lastElement; | |||
1871 | } | |||
1872 | ||||
1873 | // Invalidate the destination (regular invalidation without pointer-escaping | |||
1874 | // the address of the top-level region). This must happen before we set the | |||
1875 | // C string length because invalidation will clear the length. | |||
1876 | // FIXME: Even if we can't perfectly model the copy, we should see if we | |||
1877 | // can use LazyCompoundVals to copy the source values into the destination. | |||
1878 | // This would probably remove any existing bindings past the end of the | |||
1879 | // string, but that's still an improvement over blank invalidation. | |||
1880 | state = InvalidateBuffer(C, state, Dst, *dstRegVal, | |||
1881 | /*IsSourceBuffer*/false, nullptr); | |||
1882 | ||||
1883 | // Invalidate the source (const-invalidation without const-pointer-escaping | |||
1884 | // the address of the top-level region). | |||
1885 | state = InvalidateBuffer(C, state, srcExpr, srcVal, /*IsSourceBuffer*/true, | |||
1886 | nullptr); | |||
1887 | ||||
1888 | // Set the C string length of the destination, if we know it. | |||
1889 | if (IsBounded && (appendK == ConcatFnKind::none)) { | |||
1890 | // strncpy is annoying in that it doesn't guarantee to null-terminate | |||
1891 | // the result string. If the original string didn't fit entirely inside | |||
1892 | // the bound (including the null-terminator), we don't know how long the | |||
1893 | // result is. | |||
1894 | if (amountCopied != strLength) | |||
1895 | finalStrLength = UnknownVal(); | |||
1896 | } | |||
1897 | state = setCStringLength(state, dstRegVal->getRegion(), finalStrLength); | |||
1898 | } | |||
1899 | ||||
1900 | assert(state)((state) ? static_cast<void> (0) : __assert_fail ("state" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1900, __PRETTY_FUNCTION__)); | |||
1901 | ||||
1902 | if (returnPtr) { | |||
1903 | // If this is a stpcpy-style copy, but we were unable to check for a buffer | |||
1904 | // overflow, we still need a result. Conjure a return value. | |||
1905 | if (ReturnEnd && Result.isUnknown()) { | |||
1906 | Result = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); | |||
1907 | } | |||
1908 | } | |||
1909 | // Set the return value. | |||
1910 | state = state->BindExpr(CE, LCtx, Result); | |||
1911 | C.addTransition(state); | |||
1912 | } | |||
1913 | ||||
1914 | void CStringChecker::evalStrcmp(CheckerContext &C, const CallExpr *CE) const { | |||
1915 | //int strcmp(const char *s1, const char *s2); | |||
1916 | evalStrcmpCommon(C, CE, /* IsBounded = */ false, /* IgnoreCase = */ false); | |||
1917 | } | |||
1918 | ||||
1919 | void CStringChecker::evalStrncmp(CheckerContext &C, const CallExpr *CE) const { | |||
1920 | //int strncmp(const char *s1, const char *s2, size_t n); | |||
1921 | evalStrcmpCommon(C, CE, /* IsBounded = */ true, /* IgnoreCase = */ false); | |||
1922 | } | |||
1923 | ||||
1924 | void CStringChecker::evalStrcasecmp(CheckerContext &C, | |||
1925 | const CallExpr *CE) const { | |||
1926 | //int strcasecmp(const char *s1, const char *s2); | |||
1927 | evalStrcmpCommon(C, CE, /* IsBounded = */ false, /* IgnoreCase = */ true); | |||
1928 | } | |||
1929 | ||||
1930 | void CStringChecker::evalStrncasecmp(CheckerContext &C, | |||
1931 | const CallExpr *CE) const { | |||
1932 | //int strncasecmp(const char *s1, const char *s2, size_t n); | |||
1933 | evalStrcmpCommon(C, CE, /* IsBounded = */ true, /* IgnoreCase = */ true); | |||
| ||||
1934 | } | |||
1935 | ||||
1936 | void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, | |||
1937 | bool IsBounded, bool IgnoreCase) const { | |||
1938 | CurrentFunctionDescription = "string comparison function"; | |||
1939 | ProgramStateRef state = C.getState(); | |||
1940 | const LocationContext *LCtx = C.getLocationContext(); | |||
1941 | ||||
1942 | // Check that the first string is non-null | |||
1943 | const Expr *s1 = CE->getArg(0); | |||
1944 | SVal s1Val = state->getSVal(s1, LCtx); | |||
1945 | state = checkNonNull(C, state, s1, s1Val, 1); | |||
1946 | if (!state) | |||
1947 | return; | |||
1948 | ||||
1949 | // Check that the second string is non-null. | |||
1950 | const Expr *s2 = CE->getArg(1); | |||
1951 | SVal s2Val = state->getSVal(s2, LCtx); | |||
1952 | state = checkNonNull(C, state, s2, s2Val, 2); | |||
1953 | if (!state) | |||
1954 | return; | |||
1955 | ||||
1956 | // Get the string length of the first string or give up. | |||
1957 | SVal s1Length = getCStringLength(C, state, s1, s1Val); | |||
1958 | if (s1Length.isUndef()) | |||
1959 | return; | |||
1960 | ||||
1961 | // Get the string length of the second string or give up. | |||
1962 | SVal s2Length = getCStringLength(C, state, s2, s2Val); | |||
1963 | if (s2Length.isUndef()) | |||
1964 | return; | |||
1965 | ||||
1966 | // If we know the two buffers are the same, we know the result is 0. | |||
1967 | // First, get the two buffers' addresses. Another checker will have already | |||
1968 | // made sure they're not undefined. | |||
1969 | DefinedOrUnknownSVal LV = s1Val.castAs<DefinedOrUnknownSVal>(); | |||
1970 | DefinedOrUnknownSVal RV = s2Val.castAs<DefinedOrUnknownSVal>(); | |||
1971 | ||||
1972 | // See if they are the same. | |||
1973 | SValBuilder &svalBuilder = C.getSValBuilder(); | |||
1974 | DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); | |||
1975 | ProgramStateRef StSameBuf, StNotSameBuf; | |||
1976 | std::tie(StSameBuf, StNotSameBuf) = state->assume(SameBuf); | |||
1977 | ||||
1978 | // If the two arguments might be the same buffer, we know the result is 0, | |||
1979 | // and we only need to check one size. | |||
1980 | if (StSameBuf) { | |||
1981 | StSameBuf = StSameBuf->BindExpr(CE, LCtx, | |||
1982 | svalBuilder.makeZeroVal(CE->getType())); | |||
1983 | C.addTransition(StSameBuf); | |||
1984 | ||||
1985 | // If the two arguments are GUARANTEED to be the same, we're done! | |||
1986 | if (!StNotSameBuf) | |||
1987 | return; | |||
1988 | } | |||
1989 | ||||
1990 | assert(StNotSameBuf)((StNotSameBuf) ? static_cast<void> (0) : __assert_fail ("StNotSameBuf", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 1990, __PRETTY_FUNCTION__)); | |||
1991 | state = StNotSameBuf; | |||
1992 | ||||
1993 | // At this point we can go about comparing the two buffers. | |||
1994 | // For now, we only do this if they're both known string literals. | |||
1995 | ||||
1996 | // Attempt to extract string literals from both expressions. | |||
1997 | const StringLiteral *s1StrLiteral = getCStringLiteral(C, state, s1, s1Val); | |||
1998 | const StringLiteral *s2StrLiteral = getCStringLiteral(C, state, s2, s2Val); | |||
1999 | bool canComputeResult = false; | |||
2000 | SVal resultVal = svalBuilder.conjureSymbolVal(nullptr, CE, LCtx, | |||
2001 | C.blockCount()); | |||
2002 | ||||
2003 | if (s1StrLiteral && s2StrLiteral) { | |||
2004 | StringRef s1StrRef = s1StrLiteral->getString(); | |||
2005 | StringRef s2StrRef = s2StrLiteral->getString(); | |||
2006 | ||||
2007 | if (IsBounded) { | |||
2008 | // Get the max number of characters to compare. | |||
2009 | const Expr *lenExpr = CE->getArg(2); | |||
2010 | SVal lenVal = state->getSVal(lenExpr, LCtx); | |||
2011 | ||||
2012 | // If the length is known, we can get the right substrings. | |||
2013 | if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) { | |||
2014 | // Create substrings of each to compare the prefix. | |||
2015 | s1StrRef = s1StrRef.substr(0, (size_t)len->getZExtValue()); | |||
2016 | s2StrRef = s2StrRef.substr(0, (size_t)len->getZExtValue()); | |||
2017 | canComputeResult = true; | |||
2018 | } | |||
2019 | } else { | |||
2020 | // This is a normal, unbounded strcmp. | |||
2021 | canComputeResult = true; | |||
2022 | } | |||
2023 | ||||
2024 | if (canComputeResult) { | |||
2025 | // Real strcmp stops at null characters. | |||
2026 | size_t s1Term = s1StrRef.find('\0'); | |||
2027 | if (s1Term != StringRef::npos) | |||
2028 | s1StrRef = s1StrRef.substr(0, s1Term); | |||
2029 | ||||
2030 | size_t s2Term = s2StrRef.find('\0'); | |||
2031 | if (s2Term != StringRef::npos) | |||
2032 | s2StrRef = s2StrRef.substr(0, s2Term); | |||
2033 | ||||
2034 | // Use StringRef's comparison methods to compute the actual result. | |||
2035 | int compareRes = IgnoreCase ? s1StrRef.compare_lower(s2StrRef) | |||
2036 | : s1StrRef.compare(s2StrRef); | |||
2037 | ||||
2038 | // The strcmp function returns an integer greater than, equal to, or less | |||
2039 | // than zero, [c11, p7.24.4.2]. | |||
2040 | if (compareRes == 0) { | |||
2041 | resultVal = svalBuilder.makeIntVal(compareRes, CE->getType()); | |||
2042 | } | |||
2043 | else { | |||
2044 | DefinedSVal zeroVal = svalBuilder.makeIntVal(0, CE->getType()); | |||
2045 | // Constrain strcmp's result range based on the result of StringRef's | |||
2046 | // comparison methods. | |||
2047 | BinaryOperatorKind op = (compareRes == 1) ? BO_GT : BO_LT; | |||
2048 | SVal compareWithZero = | |||
2049 | svalBuilder.evalBinOp(state, op, resultVal, zeroVal, | |||
2050 | svalBuilder.getConditionType()); | |||
2051 | DefinedSVal compareWithZeroVal = compareWithZero.castAs<DefinedSVal>(); | |||
2052 | state = state->assume(compareWithZeroVal, true); | |||
2053 | } | |||
2054 | } | |||
2055 | } | |||
2056 | ||||
2057 | state = state->BindExpr(CE, LCtx, resultVal); | |||
2058 | ||||
2059 | // Record this as a possible path. | |||
2060 | C.addTransition(state); | |||
2061 | } | |||
2062 | ||||
2063 | void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const { | |||
2064 | //char *strsep(char **stringp, const char *delim); | |||
2065 | // Sanity: does the search string parameter match the return type? | |||
2066 | const Expr *SearchStrPtr = CE->getArg(0); | |||
2067 | QualType CharPtrTy = SearchStrPtr->getType()->getPointeeType(); | |||
2068 | if (CharPtrTy.isNull() || | |||
2069 | CE->getType().getUnqualifiedType() != CharPtrTy.getUnqualifiedType()) | |||
2070 | return; | |||
2071 | ||||
2072 | CurrentFunctionDescription = "strsep()"; | |||
2073 | ProgramStateRef State = C.getState(); | |||
2074 | const LocationContext *LCtx = C.getLocationContext(); | |||
2075 | ||||
2076 | // Check that the search string pointer is non-null (though it may point to | |||
2077 | // a null string). | |||
2078 | SVal SearchStrVal = State->getSVal(SearchStrPtr, LCtx); | |||
2079 | State = checkNonNull(C, State, SearchStrPtr, SearchStrVal, 1); | |||
2080 | if (!State) | |||
2081 | return; | |||
2082 | ||||
2083 | // Check that the delimiter string is non-null. | |||
2084 | const Expr *DelimStr = CE->getArg(1); | |||
2085 | SVal DelimStrVal = State->getSVal(DelimStr, LCtx); | |||
2086 | State = checkNonNull(C, State, DelimStr, DelimStrVal, 2); | |||
2087 | if (!State) | |||
2088 | return; | |||
2089 | ||||
2090 | SValBuilder &SVB = C.getSValBuilder(); | |||
2091 | SVal Result; | |||
2092 | if (Optional<Loc> SearchStrLoc = SearchStrVal.getAs<Loc>()) { | |||
2093 | // Get the current value of the search string pointer, as a char*. | |||
2094 | Result = State->getSVal(*SearchStrLoc, CharPtrTy); | |||
2095 | ||||
2096 | // Invalidate the search string, representing the change of one delimiter | |||
2097 | // character to NUL. | |||
2098 | State = InvalidateBuffer(C, State, SearchStrPtr, Result, | |||
2099 | /*IsSourceBuffer*/false, nullptr); | |||
2100 | ||||
2101 | // Overwrite the search string pointer. The new value is either an address | |||
2102 | // further along in the same string, or NULL if there are no more tokens. | |||
2103 | State = State->bindLoc(*SearchStrLoc, | |||
2104 | SVB.conjureSymbolVal(getTag(), | |||
2105 | CE, | |||
2106 | LCtx, | |||
2107 | CharPtrTy, | |||
2108 | C.blockCount()), | |||
2109 | LCtx); | |||
2110 | } else { | |||
2111 | assert(SearchStrVal.isUnknown())((SearchStrVal.isUnknown()) ? static_cast<void> (0) : __assert_fail ("SearchStrVal.isUnknown()", "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 2111, __PRETTY_FUNCTION__)); | |||
2112 | // Conjure a symbolic value. It's the best we can do. | |||
2113 | Result = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); | |||
2114 | } | |||
2115 | ||||
2116 | // Set the return value, and finish. | |||
2117 | State = State->BindExpr(CE, LCtx, Result); | |||
2118 | C.addTransition(State); | |||
2119 | } | |||
2120 | ||||
2121 | // These should probably be moved into a C++ standard library checker. | |||
2122 | void CStringChecker::evalStdCopy(CheckerContext &C, const CallExpr *CE) const { | |||
2123 | evalStdCopyCommon(C, CE); | |||
2124 | } | |||
2125 | ||||
2126 | void CStringChecker::evalStdCopyBackward(CheckerContext &C, | |||
2127 | const CallExpr *CE) const { | |||
2128 | evalStdCopyCommon(C, CE); | |||
2129 | } | |||
2130 | ||||
2131 | void CStringChecker::evalStdCopyCommon(CheckerContext &C, | |||
2132 | const CallExpr *CE) const { | |||
2133 | if (!CE->getArg(2)->getType()->isPointerType()) | |||
2134 | return; | |||
2135 | ||||
2136 | ProgramStateRef State = C.getState(); | |||
2137 | ||||
2138 | const LocationContext *LCtx = C.getLocationContext(); | |||
2139 | ||||
2140 | // template <class _InputIterator, class _OutputIterator> | |||
2141 | // _OutputIterator | |||
2142 | // copy(_InputIterator __first, _InputIterator __last, | |||
2143 | // _OutputIterator __result) | |||
2144 | ||||
2145 | // Invalidate the destination buffer | |||
2146 | const Expr *Dst = CE->getArg(2); | |||
2147 | SVal DstVal = State->getSVal(Dst, LCtx); | |||
2148 | State = InvalidateBuffer(C, State, Dst, DstVal, /*IsSource=*/false, | |||
2149 | /*Size=*/nullptr); | |||
2150 | ||||
2151 | SValBuilder &SVB = C.getSValBuilder(); | |||
2152 | ||||
2153 | SVal ResultVal = SVB.conjureSymbolVal(nullptr, CE, LCtx, C.blockCount()); | |||
2154 | State = State->BindExpr(CE, LCtx, ResultVal); | |||
2155 | ||||
2156 | C.addTransition(State); | |||
2157 | } | |||
2158 | ||||
2159 | void CStringChecker::evalMemset(CheckerContext &C, const CallExpr *CE) const { | |||
2160 | CurrentFunctionDescription = "memory set function"; | |||
2161 | ||||
2162 | const Expr *Mem = CE->getArg(0); | |||
2163 | const Expr *CharE = CE->getArg(1); | |||
2164 | const Expr *Size = CE->getArg(2); | |||
2165 | ProgramStateRef State = C.getState(); | |||
2166 | ||||
2167 | // See if the size argument is zero. | |||
2168 | const LocationContext *LCtx = C.getLocationContext(); | |||
2169 | SVal SizeVal = State->getSVal(Size, LCtx); | |||
2170 | QualType SizeTy = Size->getType(); | |||
2171 | ||||
2172 | ProgramStateRef StateZeroSize, StateNonZeroSize; | |||
2173 | std::tie(StateZeroSize, StateNonZeroSize) = | |||
2174 | assumeZero(C, State, SizeVal, SizeTy); | |||
2175 | ||||
2176 | // Get the value of the memory area. | |||
2177 | SVal MemVal = State->getSVal(Mem, LCtx); | |||
2178 | ||||
2179 | // If the size is zero, there won't be any actual memory access, so | |||
2180 | // just bind the return value to the Mem buffer and return. | |||
2181 | if (StateZeroSize && !StateNonZeroSize) { | |||
2182 | StateZeroSize = StateZeroSize->BindExpr(CE, LCtx, MemVal); | |||
2183 | C.addTransition(StateZeroSize); | |||
2184 | return; | |||
2185 | } | |||
2186 | ||||
2187 | // Ensure the memory area is not null. | |||
2188 | // If it is NULL there will be a NULL pointer dereference. | |||
2189 | State = checkNonNull(C, StateNonZeroSize, Mem, MemVal, 1); | |||
2190 | if (!State) | |||
2191 | return; | |||
2192 | ||||
2193 | State = CheckBufferAccess(C, State, Size, Mem); | |||
2194 | if (!State) | |||
2195 | return; | |||
2196 | ||||
2197 | // According to the values of the arguments, bind the value of the second | |||
2198 | // argument to the destination buffer and set string length, or just | |||
2199 | // invalidate the destination buffer. | |||
2200 | if (!memsetAux(Mem, C.getSVal(CharE), Size, C, State)) | |||
2201 | return; | |||
2202 | ||||
2203 | State = State->BindExpr(CE, LCtx, MemVal); | |||
2204 | C.addTransition(State); | |||
2205 | } | |||
2206 | ||||
2207 | void CStringChecker::evalBzero(CheckerContext &C, const CallExpr *CE) const { | |||
2208 | CurrentFunctionDescription = "memory clearance function"; | |||
2209 | ||||
2210 | const Expr *Mem = CE->getArg(0); | |||
2211 | const Expr *Size = CE->getArg(1); | |||
2212 | SVal Zero = C.getSValBuilder().makeZeroVal(C.getASTContext().IntTy); | |||
2213 | ||||
2214 | ProgramStateRef State = C.getState(); | |||
2215 | ||||
2216 | // See if the size argument is zero. | |||
2217 | SVal SizeVal = C.getSVal(Size); | |||
2218 | QualType SizeTy = Size->getType(); | |||
2219 | ||||
2220 | ProgramStateRef StateZeroSize, StateNonZeroSize; | |||
2221 | std::tie(StateZeroSize, StateNonZeroSize) = | |||
2222 | assumeZero(C, State, SizeVal, SizeTy); | |||
2223 | ||||
2224 | // If the size is zero, there won't be any actual memory access, | |||
2225 | // In this case we just return. | |||
2226 | if (StateZeroSize && !StateNonZeroSize) { | |||
2227 | C.addTransition(StateZeroSize); | |||
2228 | return; | |||
2229 | } | |||
2230 | ||||
2231 | // Get the value of the memory area. | |||
2232 | SVal MemVal = C.getSVal(Mem); | |||
2233 | ||||
2234 | // Ensure the memory area is not null. | |||
2235 | // If it is NULL there will be a NULL pointer dereference. | |||
2236 | State = checkNonNull(C, StateNonZeroSize, Mem, MemVal, 1); | |||
2237 | if (!State) | |||
2238 | return; | |||
2239 | ||||
2240 | State = CheckBufferAccess(C, State, Size, Mem); | |||
2241 | if (!State) | |||
2242 | return; | |||
2243 | ||||
2244 | if (!memsetAux(Mem, Zero, Size, C, State)) | |||
2245 | return; | |||
2246 | ||||
2247 | C.addTransition(State); | |||
2248 | } | |||
2249 | ||||
2250 | //===----------------------------------------------------------------------===// | |||
2251 | // The driver method, and other Checker callbacks. | |||
2252 | //===----------------------------------------------------------------------===// | |||
2253 | ||||
2254 | CStringChecker::FnCheck CStringChecker::identifyCall(const CallEvent &Call, | |||
2255 | CheckerContext &C) const { | |||
2256 | const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); | |||
2257 | if (!CE) | |||
2258 | return nullptr; | |||
2259 | ||||
2260 | const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); | |||
2261 | if (!FD) | |||
2262 | return nullptr; | |||
2263 | ||||
2264 | if (Call.isCalled(StdCopy)) { | |||
2265 | return &CStringChecker::evalStdCopy; | |||
2266 | } else if (Call.isCalled(StdCopyBackward)) { | |||
2267 | return &CStringChecker::evalStdCopyBackward; | |||
2268 | } | |||
2269 | ||||
2270 | // Pro-actively check that argument types are safe to do arithmetic upon. | |||
2271 | // We do not want to crash if someone accidentally passes a structure | |||
2272 | // into, say, a C++ overload of any of these functions. We could not check | |||
2273 | // that for std::copy because they may have arguments of other types. | |||
2274 | for (auto I : CE->arguments()) { | |||
2275 | QualType T = I->getType(); | |||
2276 | if (!T->isIntegralOrEnumerationType() && !T->isPointerType()) | |||
2277 | return nullptr; | |||
2278 | } | |||
2279 | ||||
2280 | const FnCheck *Callback = Callbacks.lookup(Call); | |||
2281 | if (Callback) | |||
2282 | return *Callback; | |||
2283 | ||||
2284 | return nullptr; | |||
2285 | } | |||
2286 | ||||
2287 | bool CStringChecker::evalCall(const CallEvent &Call, CheckerContext &C) const { | |||
2288 | FnCheck Callback = identifyCall(Call, C); | |||
2289 | ||||
2290 | // If the callee isn't a string function, let another checker handle it. | |||
2291 | if (!Callback) | |||
2292 | return false; | |||
2293 | ||||
2294 | // Check and evaluate the call. | |||
2295 | const auto *CE = cast<CallExpr>(Call.getOriginExpr()); | |||
2296 | (this->*Callback)(C, CE); | |||
2297 | ||||
2298 | // If the evaluate call resulted in no change, chain to the next eval call | |||
2299 | // handler. | |||
2300 | // Note, the custom CString evaluation calls assume that basic safety | |||
2301 | // properties are held. However, if the user chooses to turn off some of these | |||
2302 | // checks, we ignore the issues and leave the call evaluation to a generic | |||
2303 | // handler. | |||
2304 | return C.isDifferent(); | |||
2305 | } | |||
2306 | ||||
2307 | void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { | |||
2308 | // Record string length for char a[] = "abc"; | |||
2309 | ProgramStateRef state = C.getState(); | |||
2310 | ||||
2311 | for (const auto *I : DS->decls()) { | |||
2312 | const VarDecl *D = dyn_cast<VarDecl>(I); | |||
2313 | if (!D) | |||
2314 | continue; | |||
2315 | ||||
2316 | // FIXME: Handle array fields of structs. | |||
2317 | if (!D->getType()->isArrayType()) | |||
2318 | continue; | |||
2319 | ||||
2320 | const Expr *Init = D->getInit(); | |||
2321 | if (!Init) | |||
2322 | continue; | |||
2323 | if (!isa<StringLiteral>(Init)) | |||
2324 | continue; | |||
2325 | ||||
2326 | Loc VarLoc = state->getLValue(D, C.getLocationContext()); | |||
2327 | const MemRegion *MR = VarLoc.getAsRegion(); | |||
2328 | if (!MR) | |||
2329 | continue; | |||
2330 | ||||
2331 | SVal StrVal = C.getSVal(Init); | |||
2332 | assert(StrVal.isValid() && "Initializer string is unknown or undefined")((StrVal.isValid() && "Initializer string is unknown or undefined" ) ? static_cast<void> (0) : __assert_fail ("StrVal.isValid() && \"Initializer string is unknown or undefined\"" , "/build/llvm-toolchain-snapshot-10~++20200111100615+a1f16998f37/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp" , 2332, __PRETTY_FUNCTION__)); | |||
2333 | DefinedOrUnknownSVal strLength = | |||
2334 | getCStringLength(C, state, Init, StrVal).castAs<DefinedOrUnknownSVal>(); | |||
2335 | ||||
2336 | state = state->set<CStringLength>(MR, strLength); | |||
2337 | } | |||
2338 | ||||
2339 | C.addTransition(state); | |||
2340 | } | |||
2341 | ||||
2342 | ProgramStateRef | |||
2343 | CStringChecker::checkRegionChanges(ProgramStateRef state, | |||
2344 | const InvalidatedSymbols *, | |||
2345 | ArrayRef<const MemRegion *> ExplicitRegions, | |||
2346 | ArrayRef<const MemRegion *> Regions, | |||
2347 | const LocationContext *LCtx, | |||
2348 | const CallEvent *Call) const { | |||
2349 | CStringLengthTy Entries = state->get<CStringLength>(); | |||
2350 | if (Entries.isEmpty()) | |||
2351 | return state; | |||
2352 | ||||
2353 | llvm::SmallPtrSet<const MemRegion *, 8> Invalidated; | |||
2354 | llvm::SmallPtrSet<const MemRegion *, 32> SuperRegions; | |||
2355 | ||||
2356 | // First build sets for the changed regions and their super-regions. | |||
2357 | for (ArrayRef<const MemRegion *>::iterator | |||
2358 | I = Regions.begin(), E = Regions.end(); I != E; ++I) { | |||
2359 | const MemRegion *MR = *I; | |||
2360 | Invalidated.insert(MR); | |||
2361 | ||||
2362 | SuperRegions.insert(MR); | |||
2363 | while (const SubRegion *SR = dyn_cast<SubRegion>(MR)) { | |||
2364 | MR = SR->getSuperRegion(); | |||
2365 | SuperRegions.insert(MR); | |||
2366 | } | |||
2367 | } | |||
2368 | ||||
2369 | CStringLengthTy::Factory &F = state->get_context<CStringLength>(); | |||
2370 | ||||
2371 | // Then loop over the entries in the current state. | |||
2372 | for (CStringLengthTy::iterator I = Entries.begin(), | |||
2373 | E = Entries.end(); I != E; ++I) { | |||
2374 | const MemRegion *MR = I.getKey(); | |||
2375 | ||||
2376 | // Is this entry for a super-region of a changed region? | |||
2377 | if (SuperRegions.count(MR)) { | |||
2378 | Entries = F.remove(Entries, MR); | |||
2379 | continue; | |||
2380 | } | |||
2381 | ||||
2382 | // Is this entry for a sub-region of a changed region? | |||
2383 | const MemRegion *Super = MR; | |||
2384 | while (const SubRegion *SR = dyn_cast<SubRegion>(Super)) { | |||
2385 | Super = SR->getSuperRegion(); | |||
2386 | if (Invalidated.count(Super)) { | |||
2387 | Entries = F.remove(Entries, MR); | |||
2388 | break; | |||
2389 | } | |||
2390 | } | |||
2391 | } | |||
2392 | ||||
2393 | return state->set<CStringLength>(Entries); | |||
2394 | } | |||
2395 | ||||
2396 | void CStringChecker::checkLiveSymbols(ProgramStateRef state, | |||
2397 | SymbolReaper &SR) const { | |||
2398 | // Mark all symbols in our string length map as valid. | |||
2399 | CStringLengthTy Entries = state->get<CStringLength>(); | |||
2400 | ||||
2401 | for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end(); | |||
2402 | I != E; ++I) { | |||
2403 | SVal Len = I.getData(); | |||
2404 | ||||
2405 | for (SymExpr::symbol_iterator si = Len.symbol_begin(), | |||
2406 | se = Len.symbol_end(); si != se; ++si) | |||
2407 | SR.markInUse(*si); | |||
2408 | } | |||
2409 | } | |||
2410 | ||||
2411 | void CStringChecker::checkDeadSymbols(SymbolReaper &SR, | |||
2412 | CheckerContext &C) const { | |||
2413 | ProgramStateRef state = C.getState(); | |||
2414 | CStringLengthTy Entries = state->get<CStringLength>(); | |||
2415 | if (Entries.isEmpty()) | |||
2416 | return; | |||
2417 | ||||
2418 | CStringLengthTy::Factory &F = state->get_context<CStringLength>(); | |||
2419 | for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end(); | |||
2420 | I != E; ++I) { | |||
2421 | SVal Len = I.getData(); | |||
2422 | if (SymbolRef Sym = Len.getAsSymbol()) { | |||
2423 | if (SR.isDead(Sym)) | |||
2424 | Entries = F.remove(Entries, I.getKey()); | |||
2425 | } | |||
2426 | } | |||
2427 | ||||
2428 | state = state->set<CStringLength>(Entries); | |||
2429 | C.addTransition(state); | |||
2430 | } | |||
2431 | ||||
2432 | void ento::registerCStringModeling(CheckerManager &Mgr) { | |||
2433 | Mgr.registerChecker<CStringChecker>(); | |||
2434 | } | |||
2435 | ||||
2436 | bool ento::shouldRegisterCStringModeling(const LangOptions &LO) { | |||
2437 | return true; | |||
2438 | } | |||
2439 | ||||
2440 | #define REGISTER_CHECKER(name)void ento::registername(CheckerManager &mgr) { CStringChecker *checker = mgr.getChecker<CStringChecker>(); checker-> Filter.Checkname = true; checker->Filter.CheckNamename = mgr .getCurrentCheckerName(); } bool ento::shouldRegistername(const LangOptions &LO) { return true; } \ | |||
2441 | void ento::register##name(CheckerManager &mgr) { \ | |||
2442 | CStringChecker *checker = mgr.getChecker<CStringChecker>(); \ | |||
2443 | checker->Filter.Check##name = true; \ | |||
2444 | checker->Filter.CheckName##name = mgr.getCurrentCheckerName(); \ | |||
2445 | } \ | |||
2446 | \ | |||
2447 | bool ento::shouldRegister##name(const LangOptions &LO) { return true; } | |||
2448 | ||||
2449 | REGISTER_CHECKER(CStringNullArg)void ento::registerCStringNullArg(CheckerManager &mgr) { CStringChecker *checker = mgr.getChecker<CStringChecker>(); checker-> Filter.CheckCStringNullArg = true; checker->Filter.CheckNameCStringNullArg = mgr.getCurrentCheckerName(); } bool ento::shouldRegisterCStringNullArg (const LangOptions &LO) { return true; } | |||
2450 | REGISTER_CHECKER(CStringOutOfBounds)void ento::registerCStringOutOfBounds(CheckerManager &mgr ) { CStringChecker *checker = mgr.getChecker<CStringChecker >(); checker->Filter.CheckCStringOutOfBounds = true; checker ->Filter.CheckNameCStringOutOfBounds = mgr.getCurrentCheckerName (); } bool ento::shouldRegisterCStringOutOfBounds(const LangOptions &LO) { return true; } | |||
2451 | REGISTER_CHECKER(CStringBufferOverlap)void ento::registerCStringBufferOverlap(CheckerManager &mgr ) { CStringChecker *checker = mgr.getChecker<CStringChecker >(); checker->Filter.CheckCStringBufferOverlap = true; checker ->Filter.CheckNameCStringBufferOverlap = mgr.getCurrentCheckerName (); } bool ento::shouldRegisterCStringBufferOverlap(const LangOptions &LO) { return true; } | |||
2452 | REGISTER_CHECKER(CStringNotNullTerm)void ento::registerCStringNotNullTerm(CheckerManager &mgr ) { CStringChecker *checker = mgr.getChecker<CStringChecker >(); checker->Filter.CheckCStringNotNullTerm = true; checker ->Filter.CheckNameCStringNotNullTerm = mgr.getCurrentCheckerName (); } bool ento::shouldRegisterCStringNotNullTerm(const LangOptions &LO) { return true; } |