1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" |
54 | #include "clang/StaticAnalyzer/Core/Checker.h" |
55 | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
56 | #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" |
57 | #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" |
58 | |
59 | using namespace clang; |
60 | using namespace clang::ento; |
61 | |
62 | namespace { |
63 | class StdLibraryFunctionsChecker : public Checker<check::PostCall, eval::Call> { |
64 | |
65 | |
66 | |
67 | struct FunctionSummaryTy; |
68 | |
69 | |
70 | |
71 | enum InvalidationKindTy { NoEvalCall, EvalCallAsPure }; |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument }; |
80 | |
81 | |
82 | |
83 | typedef uint64_t RangeIntTy; |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy; |
90 | |
91 | |
92 | |
93 | |
94 | typedef uint32_t ArgNoTy; |
95 | static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max(); |
96 | |
97 | |
98 | class ValueRange { |
99 | ArgNoTy ArgNo; |
100 | ValueRangeKindTy Kind; |
101 | IntRangeVectorTy Args; |
102 | |
103 | public: |
104 | ValueRange(ArgNoTy ArgNo, ValueRangeKindTy Kind, |
105 | const IntRangeVectorTy &Args) |
106 | : ArgNo(ArgNo), Kind(Kind), Args(Args) {} |
107 | |
108 | ArgNoTy getArgNo() const { return ArgNo; } |
109 | ValueRangeKindTy getKind() const { return Kind; } |
110 | |
111 | BinaryOperator::Opcode getOpcode() const { |
112 | assert(Kind == ComparesToArgument); |
113 | assert(Args.size() == 1); |
114 | BinaryOperator::Opcode Op = |
115 | static_cast<BinaryOperator::Opcode>(Args[0].first); |
116 | (0) . __assert_fail ("BinaryOperator..isComparisonOp(Op) && \"Only comparison ops are supported for ComparesToArgument\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 117, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(BinaryOperator::isComparisonOp(Op) && |
117 | (0) . __assert_fail ("BinaryOperator..isComparisonOp(Op) && \"Only comparison ops are supported for ComparesToArgument\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 117, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "Only comparison ops are supported for ComparesToArgument"); |
118 | return Op; |
119 | } |
120 | |
121 | ArgNoTy getOtherArgNo() const { |
122 | assert(Kind == ComparesToArgument); |
123 | assert(Args.size() == 1); |
124 | return static_cast<ArgNoTy>(Args[0].second); |
125 | } |
126 | |
127 | const IntRangeVectorTy &getRanges() const { |
128 | assert(Kind != ComparesToArgument); |
129 | return Args; |
130 | } |
131 | |
132 | |
133 | |
134 | private: |
135 | ProgramStateRef |
136 | applyAsOutOfRange(ProgramStateRef State, const CallEvent &Call, |
137 | const FunctionSummaryTy &Summary) const; |
138 | ProgramStateRef |
139 | applyAsWithinRange(ProgramStateRef State, const CallEvent &Call, |
140 | const FunctionSummaryTy &Summary) const; |
141 | ProgramStateRef |
142 | applyAsComparesToArgument(ProgramStateRef State, const CallEvent &Call, |
143 | const FunctionSummaryTy &Summary) const; |
144 | |
145 | public: |
146 | ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, |
147 | const FunctionSummaryTy &Summary) const { |
148 | switch (Kind) { |
149 | case OutOfRange: |
150 | return applyAsOutOfRange(State, Call, Summary); |
151 | case WithinRange: |
152 | return applyAsWithinRange(State, Call, Summary); |
153 | case ComparesToArgument: |
154 | return applyAsComparesToArgument(State, Call, Summary); |
155 | } |
156 | llvm_unreachable("Unknown ValueRange kind!"); |
157 | } |
158 | }; |
159 | |
160 | |
161 | typedef std::vector<ValueRange> ValueRangeSet; |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | struct FunctionSummaryTy { |
168 | const std::vector<QualType> ArgTypes; |
169 | const QualType RetType; |
170 | const InvalidationKindTy InvalidationKind; |
171 | const std::vector<ValueRangeSet> Ranges; |
172 | |
173 | private: |
174 | static void assertTypeSuitableForSummary(QualType T) { |
175 | (0) . __assert_fail ("!T->isVoidType() && \"We should have had no significant void types in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 176, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!T->isVoidType() && |
176 | (0) . __assert_fail ("!T->isVoidType() && \"We should have had no significant void types in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 176, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "We should have had no significant void types in the spec"); |
177 | (0) . __assert_fail ("T.isCanonical() && \"We should only have canonical types in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 178, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(T.isCanonical() && |
178 | (0) . __assert_fail ("T.isCanonical() && \"We should only have canonical types in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 178, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "We should only have canonical types in the spec"); |
179 | |
180 | (0) . __assert_fail ("T->isIntegralOrEnumerationType() && \"We only support integral ranges in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 181, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(T->isIntegralOrEnumerationType() && |
181 | (0) . __assert_fail ("T->isIntegralOrEnumerationType() && \"We only support integral ranges in the spec\"", "/home/seafit/code_projects/clang_source/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp", 181, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true"> "We only support integral ranges in the spec"); |
182 | } |
183 | |
184 | public: |
185 | QualType getArgType(ArgNoTy ArgNo) const { |
186 | QualType T = (ArgNo == Ret) ? RetType : ArgTypes[ArgNo]; |
187 | assertTypeSuitableForSummary(T); |
188 | return T; |
189 | } |
190 | |
191 | |
192 | |
193 | bool matchesCall(const CallExpr *CE) const; |
194 | }; |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | typedef std::vector<FunctionSummaryTy> FunctionVariantsTy; |
202 | |
203 | |
204 | |
205 | typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy; |
206 | mutable FunctionSummaryMapTy FunctionSummaryMap; |
207 | |
208 | |
209 | |
210 | static QualType getArgType(const FunctionSummaryTy &Summary, ArgNoTy ArgNo) { |
211 | return Summary.getArgType(ArgNo); |
212 | } |
213 | static QualType getArgType(const CallEvent &Call, ArgNoTy ArgNo) { |
214 | return ArgNo == Ret ? Call.getResultType().getCanonicalType() |
215 | : Call.getArgExpr(ArgNo)->getType().getCanonicalType(); |
216 | } |
217 | static QualType getArgType(const CallExpr *CE, ArgNoTy ArgNo) { |
218 | return ArgNo == Ret ? CE->getType().getCanonicalType() |
219 | : CE->getArg(ArgNo)->getType().getCanonicalType(); |
220 | } |
221 | static SVal getArgSVal(const CallEvent &Call, ArgNoTy ArgNo) { |
222 | return ArgNo == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgNo); |
223 | } |
224 | |
225 | public: |
226 | void checkPostCall(const CallEvent &Call, CheckerContext &C) const; |
227 | bool evalCall(const CallExpr *CE, CheckerContext &C) const; |
228 | |
229 | private: |
230 | Optional<FunctionSummaryTy> findFunctionSummary(const FunctionDecl *FD, |
231 | const CallExpr *CE, |
232 | CheckerContext &C) const; |
233 | |
234 | void initFunctionSummaries(BasicValueFactory &BVF) const; |
235 | }; |
236 | } |
237 | |
238 | ProgramStateRef StdLibraryFunctionsChecker::ValueRange::applyAsOutOfRange( |
239 | ProgramStateRef State, const CallEvent &Call, |
240 | const FunctionSummaryTy &Summary) const { |
241 | |
242 | ProgramStateManager &Mgr = State->getStateManager(); |
243 | SValBuilder &SVB = Mgr.getSValBuilder(); |
244 | BasicValueFactory &BVF = SVB.getBasicValueFactory(); |
245 | ConstraintManager &CM = Mgr.getConstraintManager(); |
246 | QualType T = getArgType(Summary, getArgNo()); |
247 | SVal V = getArgSVal(Call, getArgNo()); |
248 | |
249 | if (auto N = V.getAs<NonLoc>()) { |
250 | const IntRangeVectorTy &R = getRanges(); |
251 | size_t E = R.size(); |
252 | for (size_t I = 0; I != E; ++I) { |
253 | const llvm::APSInt &Min = BVF.getValue(R[I].first, T); |
254 | const llvm::APSInt &Max = BVF.getValue(R[I].second, T); |
255 | assert(Min <= Max); |
256 | State = CM.assumeInclusiveRange(State, *N, Min, Max, false); |
257 | if (!State) |
258 | break; |
259 | } |
260 | } |
261 | |
262 | return State; |
263 | } |
264 | |
265 | ProgramStateRef |
266 | StdLibraryFunctionsChecker::ValueRange::applyAsWithinRange( |
267 | ProgramStateRef State, const CallEvent &Call, |
268 | const FunctionSummaryTy &Summary) const { |
269 | |
270 | ProgramStateManager &Mgr = State->getStateManager(); |
271 | SValBuilder &SVB = Mgr.getSValBuilder(); |
272 | BasicValueFactory &BVF = SVB.getBasicValueFactory(); |
273 | ConstraintManager &CM = Mgr.getConstraintManager(); |
274 | QualType T = getArgType(Summary, getArgNo()); |
275 | SVal V = getArgSVal(Call, getArgNo()); |
276 | |
277 | |
278 | |
279 | |
280 | if (auto N = V.getAs<NonLoc>()) { |
281 | const IntRangeVectorTy &R = getRanges(); |
282 | size_t E = R.size(); |
283 | |
284 | const llvm::APSInt &MinusInf = BVF.getMinValue(T); |
285 | const llvm::APSInt &PlusInf = BVF.getMaxValue(T); |
286 | |
287 | const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T); |
288 | if (Left != PlusInf) { |
289 | assert(MinusInf <= Left); |
290 | State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false); |
291 | if (!State) |
292 | return nullptr; |
293 | } |
294 | |
295 | const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T); |
296 | if (Right != MinusInf) { |
297 | assert(Right <= PlusInf); |
298 | State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false); |
299 | if (!State) |
300 | return nullptr; |
301 | } |
302 | |
303 | for (size_t I = 1; I != E; ++I) { |
304 | const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T); |
305 | const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T); |
306 | assert(Min <= Max); |
307 | State = CM.assumeInclusiveRange(State, *N, Min, Max, false); |
308 | if (!State) |
309 | return nullptr; |
310 | } |
311 | } |
312 | |
313 | return State; |
314 | } |
315 | |
316 | ProgramStateRef |
317 | StdLibraryFunctionsChecker::ValueRange::applyAsComparesToArgument( |
318 | ProgramStateRef State, const CallEvent &Call, |
319 | const FunctionSummaryTy &Summary) const { |
320 | |
321 | ProgramStateManager &Mgr = State->getStateManager(); |
322 | SValBuilder &SVB = Mgr.getSValBuilder(); |
323 | QualType CondT = SVB.getConditionType(); |
324 | QualType T = getArgType(Summary, getArgNo()); |
325 | SVal V = getArgSVal(Call, getArgNo()); |
326 | |
327 | BinaryOperator::Opcode Op = getOpcode(); |
328 | ArgNoTy OtherArg = getOtherArgNo(); |
329 | SVal OtherV = getArgSVal(Call, OtherArg); |
330 | QualType OtherT = getArgType(Call, OtherArg); |
331 | |
332 | OtherV = SVB.evalCast(OtherV, T, OtherT); |
333 | if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT) |
334 | .getAs<DefinedOrUnknownSVal>()) |
335 | State = State->assume(*CompV, true); |
336 | return State; |
337 | } |
338 | |
339 | void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call, |
340 | CheckerContext &C) const { |
341 | const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); |
342 | if (!FD) |
343 | return; |
344 | |
345 | const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); |
346 | if (!CE) |
347 | return; |
348 | |
349 | Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C); |
350 | if (!FoundSummary) |
351 | return; |
352 | |
353 | |
354 | const FunctionSummaryTy &Summary = *FoundSummary; |
355 | ProgramStateRef State = C.getState(); |
356 | |
357 | for (const auto &VRS: Summary.Ranges) { |
358 | ProgramStateRef NewState = State; |
359 | for (const auto &VR: VRS) { |
360 | NewState = VR.apply(NewState, Call, Summary); |
361 | if (!NewState) |
362 | break; |
363 | } |
364 | |
365 | if (NewState && NewState != State) |
366 | C.addTransition(NewState); |
367 | } |
368 | } |
369 | |
370 | bool StdLibraryFunctionsChecker::evalCall(const CallExpr *CE, |
371 | CheckerContext &C) const { |
372 | const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); |
373 | if (!FD) |
374 | return false; |
375 | |
376 | Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C); |
377 | if (!FoundSummary) |
378 | return false; |
379 | |
380 | const FunctionSummaryTy &Summary = *FoundSummary; |
381 | switch (Summary.InvalidationKind) { |
382 | case EvalCallAsPure: { |
383 | ProgramStateRef State = C.getState(); |
384 | const LocationContext *LC = C.getLocationContext(); |
385 | SVal V = C.getSValBuilder().conjureSymbolVal( |
386 | CE, LC, CE->getType().getCanonicalType(), C.blockCount()); |
387 | State = State->BindExpr(CE, LC, V); |
388 | C.addTransition(State); |
389 | return true; |
390 | } |
391 | case NoEvalCall: |
392 | |
393 | |
394 | return false; |
395 | } |
396 | llvm_unreachable("Unknown invalidation kind!"); |
397 | } |
398 | |
399 | bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall( |
400 | const CallExpr *CE) const { |
401 | |
402 | if (CE->getNumArgs() != ArgTypes.size()) |
403 | return false; |
404 | |
405 | |
406 | if (!RetType.isNull() && RetType != CE->getType().getCanonicalType()) |
407 | return false; |
408 | |
409 | |
410 | for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) { |
411 | QualType FormalT = ArgTypes[I]; |
412 | |
413 | if (FormalT.isNull()) |
414 | continue; |
415 | |
416 | assertTypeSuitableForSummary(FormalT); |
417 | |
418 | QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I); |
419 | assert(ActualT.isCanonical()); |
420 | if (ActualT != FormalT) |
421 | return false; |
422 | } |
423 | |
424 | return true; |
425 | } |
426 | |
427 | Optional<StdLibraryFunctionsChecker::FunctionSummaryTy> |
428 | StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD, |
429 | const CallExpr *CE, |
430 | CheckerContext &C) const { |
431 | |
432 | |
433 | assert(CE); |
434 | |
435 | if (!FD) |
436 | return None; |
437 | |
438 | SValBuilder &SVB = C.getSValBuilder(); |
439 | BasicValueFactory &BVF = SVB.getBasicValueFactory(); |
440 | initFunctionSummaries(BVF); |
441 | |
442 | IdentifierInfo *II = FD->getIdentifier(); |
443 | if (!II) |
444 | return None; |
445 | StringRef Name = II->getName(); |
446 | if (Name.empty() || !C.isCLibraryFunction(FD, Name)) |
447 | return None; |
448 | |
449 | auto FSMI = FunctionSummaryMap.find(Name); |
450 | if (FSMI == FunctionSummaryMap.end()) |
451 | return None; |
452 | |
453 | |
454 | |
455 | |
456 | |
457 | |
458 | const FunctionVariantsTy &SpecVariants = FSMI->second; |
459 | for (const FunctionSummaryTy &Spec : SpecVariants) |
460 | if (Spec.matchesCall(CE)) |
461 | return Spec; |
462 | |
463 | return None; |
464 | } |
465 | |
466 | void StdLibraryFunctionsChecker::initFunctionSummaries( |
467 | BasicValueFactory &BVF) const { |
468 | if (!FunctionSummaryMap.empty()) |
469 | return; |
470 | |
471 | ASTContext &ACtx = BVF.getContext(); |
472 | |
473 | |
474 | |
475 | |
476 | |
477 | |
478 | |
479 | |
480 | QualType Irrelevant; |
481 | QualType IntTy = ACtx.IntTy; |
482 | QualType LongTy = ACtx.LongTy; |
483 | QualType LongLongTy = ACtx.LongLongTy; |
484 | QualType SizeTy = ACtx.getSizeType(); |
485 | |
486 | RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); |
487 | RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue(); |
488 | RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue(); |
489 | |
490 | |
491 | |
492 | |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | |
524 | |
525 | |
526 | |
527 | |
528 | |
529 | |
530 | |
531 | #define SUMMARY_WITH_VARIANTS(identifier) {#identifier, { |
532 | #define END_SUMMARY_WITH_VARIANTS }}, |
533 | #define VARIANT(argument_types, return_type, invalidation_approach) \ |
534 | { argument_types, return_type, invalidation_approach, { |
535 | #define END_VARIANT } }, |
536 | #define SUMMARY(identifier, argument_types, return_type, \ |
537 | invalidation_approach) \ |
538 | { #identifier, { { argument_types, return_type, invalidation_approach, { |
539 | #define END_SUMMARY } } } }, |
540 | #define ARGUMENT_TYPES(...) { __VA_ARGS__ } |
541 | #define RETURN_TYPE(x) x |
542 | #define INVALIDATION_APPROACH(x) x |
543 | #define CASE { |
544 | #define END_CASE }, |
545 | #define ARGUMENT_CONDITION(argument_number, condition_kind) \ |
546 | { argument_number, condition_kind, { |
547 | #define END_ARGUMENT_CONDITION }}, |
548 | #define RETURN_VALUE_CONDITION(condition_kind) \ |
549 | { Ret, condition_kind, { |
550 | #define END_RETURN_VALUE_CONDITION }}, |
551 | #define ARG_NO(x) x##U |
552 | #define RANGE(x, y) { x, y }, |
553 | #define SINGLE_VALUE(x) RANGE(x, x) |
554 | #define IS_LESS_THAN(arg) { BO_LE, arg } |
555 | |
556 | FunctionSummaryMap = { |
557 | |
558 | SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
559 | INVALIDATION_APPROACH(EvalCallAsPure)) |
560 | CASE |
561 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
562 | RANGE('0', '9') |
563 | RANGE('A', 'Z') |
564 | RANGE('a', 'z') |
565 | END_ARGUMENT_CONDITION |
566 | RETURN_VALUE_CONDITION(OutOfRange) |
567 | SINGLE_VALUE(0) |
568 | END_RETURN_VALUE_CONDITION |
569 | END_CASE |
570 | CASE |
571 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
572 | RANGE(128, 255) |
573 | END_ARGUMENT_CONDITION |
574 | |
575 | |
576 | END_CASE |
577 | CASE |
578 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
579 | RANGE('0', '9') |
580 | RANGE('A', 'Z') |
581 | RANGE('a', 'z') |
582 | RANGE(128, 255) |
583 | END_ARGUMENT_CONDITION |
584 | RETURN_VALUE_CONDITION(WithinRange) |
585 | SINGLE_VALUE(0) |
586 | END_RETURN_VALUE_CONDITION |
587 | END_CASE |
588 | END_SUMMARY |
589 | SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
590 | INVALIDATION_APPROACH(EvalCallAsPure)) |
591 | CASE |
592 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
593 | RANGE('A', 'Z') |
594 | RANGE('a', 'z') |
595 | END_ARGUMENT_CONDITION |
596 | RETURN_VALUE_CONDITION(OutOfRange) |
597 | SINGLE_VALUE(0) |
598 | END_RETURN_VALUE_CONDITION |
599 | END_CASE |
600 | CASE |
601 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
602 | RANGE(128, 255) |
603 | END_ARGUMENT_CONDITION |
604 | END_CASE |
605 | CASE |
606 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
607 | RANGE('A', 'Z') |
608 | RANGE('a', 'z') |
609 | RANGE(128, 255) |
610 | END_ARGUMENT_CONDITION |
611 | RETURN_VALUE_CONDITION(WithinRange) |
612 | SINGLE_VALUE(0) |
613 | END_RETURN_VALUE_CONDITION |
614 | END_CASE |
615 | END_SUMMARY |
616 | SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
617 | INVALIDATION_APPROACH(EvalCallAsPure)) |
618 | CASE |
619 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
620 | RANGE(0, 127) |
621 | END_ARGUMENT_CONDITION |
622 | RETURN_VALUE_CONDITION(OutOfRange) |
623 | SINGLE_VALUE(0) |
624 | END_RETURN_VALUE_CONDITION |
625 | END_CASE |
626 | CASE |
627 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
628 | RANGE(0, 127) |
629 | END_ARGUMENT_CONDITION |
630 | RETURN_VALUE_CONDITION(WithinRange) |
631 | SINGLE_VALUE(0) |
632 | END_RETURN_VALUE_CONDITION |
633 | END_CASE |
634 | END_SUMMARY |
635 | SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
636 | INVALIDATION_APPROACH(EvalCallAsPure)) |
637 | CASE |
638 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
639 | SINGLE_VALUE('\t') |
640 | SINGLE_VALUE(' ') |
641 | END_ARGUMENT_CONDITION |
642 | RETURN_VALUE_CONDITION(OutOfRange) |
643 | SINGLE_VALUE(0) |
644 | END_RETURN_VALUE_CONDITION |
645 | END_CASE |
646 | CASE |
647 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
648 | SINGLE_VALUE('\t') |
649 | SINGLE_VALUE(' ') |
650 | END_ARGUMENT_CONDITION |
651 | RETURN_VALUE_CONDITION(WithinRange) |
652 | SINGLE_VALUE(0) |
653 | END_RETURN_VALUE_CONDITION |
654 | END_CASE |
655 | END_SUMMARY |
656 | SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
657 | INVALIDATION_APPROACH(EvalCallAsPure)) |
658 | CASE |
659 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
660 | RANGE(0, 32) |
661 | SINGLE_VALUE(127) |
662 | END_ARGUMENT_CONDITION |
663 | RETURN_VALUE_CONDITION(OutOfRange) |
664 | SINGLE_VALUE(0) |
665 | END_RETURN_VALUE_CONDITION |
666 | END_CASE |
667 | CASE |
668 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
669 | RANGE(0, 32) |
670 | SINGLE_VALUE(127) |
671 | END_ARGUMENT_CONDITION |
672 | RETURN_VALUE_CONDITION(WithinRange) |
673 | SINGLE_VALUE(0) |
674 | END_RETURN_VALUE_CONDITION |
675 | END_CASE |
676 | END_SUMMARY |
677 | SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
678 | INVALIDATION_APPROACH(EvalCallAsPure)) |
679 | CASE |
680 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
681 | RANGE('0', '9') |
682 | END_ARGUMENT_CONDITION |
683 | RETURN_VALUE_CONDITION(OutOfRange) |
684 | SINGLE_VALUE(0) |
685 | END_RETURN_VALUE_CONDITION |
686 | END_CASE |
687 | CASE |
688 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
689 | RANGE('0', '9') |
690 | END_ARGUMENT_CONDITION |
691 | RETURN_VALUE_CONDITION(WithinRange) |
692 | SINGLE_VALUE(0) |
693 | END_RETURN_VALUE_CONDITION |
694 | END_CASE |
695 | END_SUMMARY |
696 | SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
697 | INVALIDATION_APPROACH(EvalCallAsPure)) |
698 | CASE |
699 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
700 | RANGE(33, 126) |
701 | END_ARGUMENT_CONDITION |
702 | RETURN_VALUE_CONDITION(OutOfRange) |
703 | SINGLE_VALUE(0) |
704 | END_RETURN_VALUE_CONDITION |
705 | END_CASE |
706 | CASE |
707 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
708 | RANGE(33, 126) |
709 | END_ARGUMENT_CONDITION |
710 | RETURN_VALUE_CONDITION(WithinRange) |
711 | SINGLE_VALUE(0) |
712 | END_RETURN_VALUE_CONDITION |
713 | END_CASE |
714 | END_SUMMARY |
715 | SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
716 | INVALIDATION_APPROACH(EvalCallAsPure)) |
717 | CASE |
718 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
719 | RANGE('a', 'z') |
720 | END_ARGUMENT_CONDITION |
721 | RETURN_VALUE_CONDITION(OutOfRange) |
722 | SINGLE_VALUE(0) |
723 | END_RETURN_VALUE_CONDITION |
724 | END_CASE |
725 | CASE |
726 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
727 | RANGE(0, 127) |
728 | END_ARGUMENT_CONDITION |
729 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
730 | RANGE('a', 'z') |
731 | END_ARGUMENT_CONDITION |
732 | RETURN_VALUE_CONDITION(WithinRange) |
733 | SINGLE_VALUE(0) |
734 | END_RETURN_VALUE_CONDITION |
735 | END_CASE |
736 | CASE |
737 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
738 | RANGE(128, 255) |
739 | END_ARGUMENT_CONDITION |
740 | END_CASE |
741 | CASE |
742 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
743 | RANGE(0, 255) |
744 | END_ARGUMENT_CONDITION |
745 | RETURN_VALUE_CONDITION(WithinRange) |
746 | SINGLE_VALUE(0) |
747 | END_RETURN_VALUE_CONDITION |
748 | END_CASE |
749 | END_SUMMARY |
750 | SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
751 | INVALIDATION_APPROACH(EvalCallAsPure)) |
752 | CASE |
753 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
754 | RANGE(32, 126) |
755 | END_ARGUMENT_CONDITION |
756 | RETURN_VALUE_CONDITION(OutOfRange) |
757 | SINGLE_VALUE(0) |
758 | END_RETURN_VALUE_CONDITION |
759 | END_CASE |
760 | CASE |
761 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
762 | RANGE(32, 126) |
763 | END_ARGUMENT_CONDITION |
764 | RETURN_VALUE_CONDITION(WithinRange) |
765 | SINGLE_VALUE(0) |
766 | END_RETURN_VALUE_CONDITION |
767 | END_CASE |
768 | END_SUMMARY |
769 | SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
770 | INVALIDATION_APPROACH(EvalCallAsPure)) |
771 | CASE |
772 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
773 | RANGE('!', '/') |
774 | RANGE(':', '@') |
775 | RANGE('[', '`') |
776 | RANGE('{', '~') |
777 | END_ARGUMENT_CONDITION |
778 | RETURN_VALUE_CONDITION(OutOfRange) |
779 | SINGLE_VALUE(0) |
780 | END_RETURN_VALUE_CONDITION |
781 | END_CASE |
782 | CASE |
783 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
784 | RANGE('!', '/') |
785 | RANGE(':', '@') |
786 | RANGE('[', '`') |
787 | RANGE('{', '~') |
788 | END_ARGUMENT_CONDITION |
789 | RETURN_VALUE_CONDITION(WithinRange) |
790 | SINGLE_VALUE(0) |
791 | END_RETURN_VALUE_CONDITION |
792 | END_CASE |
793 | END_SUMMARY |
794 | SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
795 | INVALIDATION_APPROACH(EvalCallAsPure)) |
796 | CASE |
797 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
798 | RANGE(9, 13) |
799 | SINGLE_VALUE(' ') |
800 | END_ARGUMENT_CONDITION |
801 | RETURN_VALUE_CONDITION(OutOfRange) |
802 | SINGLE_VALUE(0) |
803 | END_RETURN_VALUE_CONDITION |
804 | END_CASE |
805 | CASE |
806 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
807 | RANGE(128, 255) |
808 | END_ARGUMENT_CONDITION |
809 | END_CASE |
810 | CASE |
811 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
812 | RANGE(9, 13) |
813 | SINGLE_VALUE(' ') |
814 | RANGE(128, 255) |
815 | END_ARGUMENT_CONDITION |
816 | RETURN_VALUE_CONDITION(WithinRange) |
817 | SINGLE_VALUE(0) |
818 | END_RETURN_VALUE_CONDITION |
819 | END_CASE |
820 | END_SUMMARY |
821 | SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy), |
822 | INVALIDATION_APPROACH(EvalCallAsPure)) |
823 | CASE |
824 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
825 | RANGE('A', 'Z') |
826 | END_ARGUMENT_CONDITION |
827 | RETURN_VALUE_CONDITION(OutOfRange) |
828 | SINGLE_VALUE(0) |
829 | END_RETURN_VALUE_CONDITION |
830 | END_CASE |
831 | CASE |
832 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
833 | RANGE(128, 255) |
834 | END_ARGUMENT_CONDITION |
835 | END_CASE |
836 | CASE |
837 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
838 | RANGE('A', 'Z') RANGE(128, 255) |
839 | END_ARGUMENT_CONDITION |
840 | RETURN_VALUE_CONDITION(WithinRange) |
841 | SINGLE_VALUE(0) |
842 | END_RETURN_VALUE_CONDITION |
843 | END_CASE |
844 | END_SUMMARY |
845 | SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), |
846 | INVALIDATION_APPROACH(EvalCallAsPure)) |
847 | CASE |
848 | ARGUMENT_CONDITION(ARG_NO(0), WithinRange) |
849 | RANGE('0', '9') |
850 | RANGE('A', 'F') |
851 | RANGE('a', 'f') |
852 | END_ARGUMENT_CONDITION |
853 | RETURN_VALUE_CONDITION(OutOfRange) |
854 | SINGLE_VALUE(0) |
855 | END_RETURN_VALUE_CONDITION |
856 | END_CASE |
857 | CASE |
858 | ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) |
859 | RANGE('0', '9') |
860 | RANGE('A', 'F') |
861 | RANGE('a', 'f') |
862 | END_ARGUMENT_CONDITION |
863 | RETURN_VALUE_CONDITION(WithinRange) |
864 | SINGLE_VALUE(0) |
865 | END_RETURN_VALUE_CONDITION |
866 | END_CASE |
867 | END_SUMMARY |
868 | |
869 | |
870 | SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy), |
871 | INVALIDATION_APPROACH(NoEvalCall)) |
872 | CASE |
873 | RETURN_VALUE_CONDITION(WithinRange) |
874 | RANGE(-1, 255) |
875 | END_RETURN_VALUE_CONDITION |
876 | END_CASE |
877 | END_SUMMARY |
878 | SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy), |
879 | INVALIDATION_APPROACH(NoEvalCall)) |
880 | CASE |
881 | RETURN_VALUE_CONDITION(WithinRange) |
882 | RANGE(-1, 255) |
883 | END_RETURN_VALUE_CONDITION |
884 | END_CASE |
885 | END_SUMMARY |
886 | SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy), |
887 | INVALIDATION_APPROACH(NoEvalCall)) |
888 | CASE |
889 | RETURN_VALUE_CONDITION(WithinRange) |
890 | RANGE(-1, 255) |
891 | END_RETURN_VALUE_CONDITION |
892 | END_CASE |
893 | END_SUMMARY |
894 | |
895 | |
896 | |
897 | |
898 | SUMMARY_WITH_VARIANTS(read) |
899 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
900 | RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) |
901 | CASE |
902 | RETURN_VALUE_CONDITION(ComparesToArgument) |
903 | IS_LESS_THAN(ARG_NO(2)) |
904 | END_RETURN_VALUE_CONDITION |
905 | RETURN_VALUE_CONDITION(WithinRange) |
906 | RANGE(-1, IntMax) |
907 | END_RETURN_VALUE_CONDITION |
908 | END_CASE |
909 | END_VARIANT |
910 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
911 | RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) |
912 | CASE |
913 | RETURN_VALUE_CONDITION(ComparesToArgument) |
914 | IS_LESS_THAN(ARG_NO(2)) |
915 | END_RETURN_VALUE_CONDITION |
916 | RETURN_VALUE_CONDITION(WithinRange) |
917 | RANGE(-1, LongMax) |
918 | END_RETURN_VALUE_CONDITION |
919 | END_CASE |
920 | END_VARIANT |
921 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
922 | RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) |
923 | CASE |
924 | RETURN_VALUE_CONDITION(ComparesToArgument) |
925 | IS_LESS_THAN(ARG_NO(2)) |
926 | END_RETURN_VALUE_CONDITION |
927 | RETURN_VALUE_CONDITION(WithinRange) |
928 | RANGE(-1, LongLongMax) |
929 | END_RETURN_VALUE_CONDITION |
930 | END_CASE |
931 | END_VARIANT |
932 | END_SUMMARY_WITH_VARIANTS |
933 | SUMMARY_WITH_VARIANTS(write) |
934 | |
935 | |
936 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
937 | RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) |
938 | CASE |
939 | RETURN_VALUE_CONDITION(ComparesToArgument) |
940 | IS_LESS_THAN(ARG_NO(2)) |
941 | END_RETURN_VALUE_CONDITION |
942 | RETURN_VALUE_CONDITION(WithinRange) |
943 | RANGE(-1, IntMax) |
944 | END_RETURN_VALUE_CONDITION |
945 | END_CASE |
946 | END_VARIANT |
947 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
948 | RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) |
949 | CASE |
950 | RETURN_VALUE_CONDITION(ComparesToArgument) |
951 | IS_LESS_THAN(ARG_NO(2)) |
952 | END_RETURN_VALUE_CONDITION |
953 | RETURN_VALUE_CONDITION(WithinRange) |
954 | RANGE(-1, LongMax) |
955 | END_RETURN_VALUE_CONDITION |
956 | END_CASE |
957 | END_VARIANT |
958 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), |
959 | RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) |
960 | CASE |
961 | RETURN_VALUE_CONDITION(ComparesToArgument) |
962 | IS_LESS_THAN(ARG_NO(2)) |
963 | END_RETURN_VALUE_CONDITION |
964 | RETURN_VALUE_CONDITION(WithinRange) |
965 | RANGE(-1, LongLongMax) |
966 | END_RETURN_VALUE_CONDITION |
967 | END_CASE |
968 | END_VARIANT |
969 | END_SUMMARY_WITH_VARIANTS |
970 | SUMMARY(fread, |
971 | ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant), |
972 | RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall)) |
973 | CASE |
974 | RETURN_VALUE_CONDITION(ComparesToArgument) |
975 | IS_LESS_THAN(ARG_NO(2)) |
976 | END_RETURN_VALUE_CONDITION |
977 | END_CASE |
978 | END_SUMMARY |
979 | SUMMARY(fwrite, |
980 | ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant), |
981 | RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall)) |
982 | CASE |
983 | RETURN_VALUE_CONDITION(ComparesToArgument) |
984 | IS_LESS_THAN(ARG_NO(2)) |
985 | END_RETURN_VALUE_CONDITION |
986 | END_CASE |
987 | END_SUMMARY |
988 | |
989 | |
990 | SUMMARY_WITH_VARIANTS(getline) |
991 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), |
992 | RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) |
993 | CASE |
994 | RETURN_VALUE_CONDITION(WithinRange) |
995 | SINGLE_VALUE(-1) |
996 | RANGE(1, IntMax) |
997 | END_RETURN_VALUE_CONDITION |
998 | END_CASE |
999 | END_VARIANT |
1000 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), |
1001 | RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) |
1002 | CASE |
1003 | RETURN_VALUE_CONDITION(WithinRange) |
1004 | SINGLE_VALUE(-1) |
1005 | RANGE(1, LongMax) |
1006 | END_RETURN_VALUE_CONDITION |
1007 | END_CASE |
1008 | END_VARIANT |
1009 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), |
1010 | RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) |
1011 | CASE |
1012 | RETURN_VALUE_CONDITION(WithinRange) |
1013 | SINGLE_VALUE(-1) |
1014 | RANGE(1, LongLongMax) |
1015 | END_RETURN_VALUE_CONDITION |
1016 | END_CASE |
1017 | END_VARIANT |
1018 | END_SUMMARY_WITH_VARIANTS |
1019 | SUMMARY_WITH_VARIANTS(getdelim) |
1020 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), |
1021 | RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) |
1022 | CASE |
1023 | RETURN_VALUE_CONDITION(WithinRange) |
1024 | SINGLE_VALUE(-1) |
1025 | RANGE(1, IntMax) |
1026 | END_RETURN_VALUE_CONDITION |
1027 | END_CASE |
1028 | END_VARIANT |
1029 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), |
1030 | RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) |
1031 | CASE |
1032 | RETURN_VALUE_CONDITION(WithinRange) |
1033 | SINGLE_VALUE(-1) |
1034 | RANGE(1, LongMax) |
1035 | END_RETURN_VALUE_CONDITION |
1036 | END_CASE |
1037 | END_VARIANT |
1038 | VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), |
1039 | RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) |
1040 | CASE |
1041 | RETURN_VALUE_CONDITION(WithinRange) |
1042 | SINGLE_VALUE(-1) |
1043 | RANGE(1, LongLongMax) |
1044 | END_RETURN_VALUE_CONDITION |
1045 | END_CASE |
1046 | END_VARIANT |
1047 | END_SUMMARY_WITH_VARIANTS |
1048 | }; |
1049 | } |
1050 | |
1051 | void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) { |
1052 | |
1053 | |
1054 | |
1055 | |
1056 | mgr.registerChecker<StdLibraryFunctionsChecker>(); |
1057 | } |
1058 | |
1059 | bool ento::shouldRegisterStdCLibraryFunctionsChecker(const LangOptions &LO) { |
1060 | return true; |
1061 | } |
1062 | |