]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / StaticAnalyzer / Checkers / StdLibraryFunctionsChecker.cpp
1 //=== StdLibraryFunctionsChecker.cpp - Model standard 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 checker improves modeling of a few simple library functions.
10 // It does not generate warnings.
11 //
12 // This checker provides a specification format - `FunctionSummaryTy' - and
13 // contains descriptions of some library functions in this format. Each
14 // specification contains a list of branches for splitting the program state
15 // upon call, and range constraints on argument and return-value symbols that
16 // are satisfied on each branch. This spec can be expanded to include more
17 // items, like external effects of the function.
18 //
19 // The main difference between this approach and the body farms technique is
20 // in more explicit control over how many branches are produced. For example,
21 // consider standard C function `ispunct(int x)', which returns a non-zero value
22 // iff `x' is a punctuation character, that is, when `x' is in range
23 //   ['!', '/']   [':', '@']  U  ['[', '\`']  U  ['{', '~'].
24 // `FunctionSummaryTy' provides only two branches for this function. However,
25 // any attempt to describe this range with if-statements in the body farm
26 // would result in many more branches. Because each branch needs to be analyzed
27 // independently, this significantly reduces performance. Additionally,
28 // once we consider a branch on which `x' is in range, say, ['!', '/'],
29 // we assume that such branch is an important separate path through the program,
30 // which may lead to false positives because considering this particular path
31 // was not consciously intended, and therefore it might have been unreachable.
32 //
33 // This checker uses eval::Call for modeling "pure" functions, for which
34 // their `FunctionSummaryTy' is a precise model. This avoids unnecessary
35 // invalidation passes. Conflicts with other checkers are unlikely because
36 // if the function has no other effects, other checkers would probably never
37 // want to improve upon the modeling done by this checker.
38 //
39 // Non-"pure" functions, for which only partial improvement over the default
40 // behavior is expected, are modeled via check::PostCall, non-intrusively.
41 //
42 // The following standard C functions are currently supported:
43 //
44 //   fgetc      getline   isdigit   isupper
45 //   fread      isalnum   isgraph   isxdigit
46 //   fwrite     isalpha   islower   read
47 //   getc       isascii   isprint   write
48 //   getchar    isblank   ispunct
49 //   getdelim   iscntrl   isspace
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   /// Below is a series of typedefs necessary to define function specs.
65   /// We avoid nesting types here because each additional qualifier
66   /// would need to be repeated in every function spec.
67   struct FunctionSummaryTy;
68
69   /// Specify how much the analyzer engine should entrust modeling this function
70   /// to us. If he doesn't, he performs additional invalidations.
71   enum InvalidationKindTy { NoEvalCall, EvalCallAsPure };
72
73   /// A pair of ValueRangeKindTy and IntRangeVectorTy would describe a range
74   /// imposed on a particular argument or return value symbol.
75   ///
76   /// Given a range, should the argument stay inside or outside this range?
77   /// The special `ComparesToArgument' value indicates that we should
78   /// impose a constraint that involves other argument or return value symbols.
79   enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument };
80
81   // The universal integral type to use in value range descriptions.
82   // Unsigned to make sure overflows are well-defined.
83   typedef uint64_t RangeIntTy;
84
85   /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
86   /// a non-negative integer, which less than 5 and not equal to 2. For
87   /// `ComparesToArgument', holds information about how exactly to compare to
88   /// the argument.
89   typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy;
90
91   /// A reference to an argument or return value by its number.
92   /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
93   /// obviously uint32_t should be enough for all practical purposes.
94   typedef uint32_t ArgNoTy;
95   static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max();
96
97   /// Incapsulates a single range on a single symbol within a branch.
98   class ValueRange {
99     ArgNoTy ArgNo; // Argument to which we apply the range.
100     ValueRangeKindTy Kind; // Kind of range definition.
101     IntRangeVectorTy Args; // Polymorphic arguments.
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       assert(BinaryOperator::isComparisonOp(Op) &&
117              "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     // We avoid creating a virtual apply() method because
133     // it makes initializer lists harder to write.
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   /// The complete list of ranges that defines a single branch.
161   typedef std::vector<ValueRange> ValueRangeSet;
162
163   /// Includes information about function prototype (which is necessary to
164   /// ensure we're modeling the right function and casting values properly),
165   /// approach to invalidation, and a list of branches - essentially, a list
166   /// of list of ranges - essentially, a list of lists of lists of segments.
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       assert(!T->isVoidType() &&
176              "We should have had no significant void types in the spec");
177       assert(T.isCanonical() &&
178              "We should only have canonical types in the spec");
179       // FIXME: lift this assert (but not the ones above!)
180       assert(T->isIntegralOrEnumerationType() &&
181              "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     /// Try our best to figure out if the call expression is the call of
192     /// *the* library function to which this specification applies.
193     bool matchesCall(const CallExpr *CE) const;
194   };
195
196   // The same function (as in, function identifier) may have different
197   // summaries assigned to it, with different argument and return value types.
198   // We call these "variants" of the function. This can be useful for handling
199   // C++ function overloads, and also it can be used when the same function
200   // may have different definitions on different platforms.
201   typedef std::vector<FunctionSummaryTy> FunctionVariantsTy;
202
203   // The map of all functions supported by the checker. It is initialized
204   // lazily, and it doesn't change after initialization.
205   typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy;
206   mutable FunctionSummaryMapTy FunctionSummaryMap;
207
208   // Auxiliary functions to support ArgNoTy within all structures
209   // in a unified manner.
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 CallEvent &Call, 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 } // end of anonymous namespace
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   // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
278   // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
279   // and then cut away all holes in R one by one.
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   // Note: we avoid integral promotion for comparison.
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   // Now apply ranges.
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 CallEvent &Call,
371                                           CheckerContext &C) const {
372   const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
373   if (!FD)
374     return false;
375
376   const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
377   if (!CE)
378     return false;
379
380   Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
381   if (!FoundSummary)
382     return false;
383
384   const FunctionSummaryTy &Summary = *FoundSummary;
385   switch (Summary.InvalidationKind) {
386   case EvalCallAsPure: {
387     ProgramStateRef State = C.getState();
388     const LocationContext *LC = C.getLocationContext();
389     SVal V = C.getSValBuilder().conjureSymbolVal(
390         CE, LC, CE->getType().getCanonicalType(), C.blockCount());
391     State = State->BindExpr(CE, LC, V);
392     C.addTransition(State);
393     return true;
394   }
395   case NoEvalCall:
396     // Summary tells us to avoid performing eval::Call. The function is possibly
397     // evaluated by another checker, or evaluated conservatively.
398     return false;
399   }
400   llvm_unreachable("Unknown invalidation kind!");
401 }
402
403 bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall(
404     const CallExpr *CE) const {
405   // Check number of arguments:
406   if (CE->getNumArgs() != ArgTypes.size())
407     return false;
408
409   // Check return type if relevant:
410   if (!RetType.isNull() && RetType != CE->getType().getCanonicalType())
411     return false;
412
413   // Check argument types when relevant:
414   for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) {
415     QualType FormalT = ArgTypes[I];
416     // Null type marks irrelevant arguments.
417     if (FormalT.isNull())
418       continue;
419
420     assertTypeSuitableForSummary(FormalT);
421
422     QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I);
423     assert(ActualT.isCanonical());
424     if (ActualT != FormalT)
425       return false;
426   }
427
428   return true;
429 }
430
431 Optional<StdLibraryFunctionsChecker::FunctionSummaryTy>
432 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
433                                                 const CallExpr *CE,
434                                                 CheckerContext &C) const {
435   // Note: we cannot always obtain FD from CE
436   // (eg. virtual call, or call by pointer).
437   assert(CE);
438
439   if (!FD)
440     return None;
441
442   SValBuilder &SVB = C.getSValBuilder();
443   BasicValueFactory &BVF = SVB.getBasicValueFactory();
444   initFunctionSummaries(BVF);
445
446   IdentifierInfo *II = FD->getIdentifier();
447   if (!II)
448     return None;
449   StringRef Name = II->getName();
450   if (Name.empty() || !C.isCLibraryFunction(FD, Name))
451     return None;
452
453   auto FSMI = FunctionSummaryMap.find(Name);
454   if (FSMI == FunctionSummaryMap.end())
455     return None;
456
457   // Verify that function signature matches the spec in advance.
458   // Otherwise we might be modeling the wrong function.
459   // Strict checking is important because we will be conducting
460   // very integral-type-sensitive operations on arguments and
461   // return values.
462   const FunctionVariantsTy &SpecVariants = FSMI->second;
463   for (const FunctionSummaryTy &Spec : SpecVariants)
464     if (Spec.matchesCall(CE))
465       return Spec;
466
467   return None;
468 }
469
470 void StdLibraryFunctionsChecker::initFunctionSummaries(
471     BasicValueFactory &BVF) const {
472   if (!FunctionSummaryMap.empty())
473     return;
474
475   ASTContext &ACtx = BVF.getContext();
476
477   // These types are useful for writing specifications quickly,
478   // New specifications should probably introduce more types.
479   // Some types are hard to obtain from the AST, eg. "ssize_t".
480   // In such cases it should be possible to provide multiple variants
481   // of function summary for common cases (eg. ssize_t could be int or long
482   // or long long, so three summary variants would be enough).
483   // Of course, function variants are also useful for C++ overloads.
484   QualType Irrelevant; // A placeholder, whenever we do not care about the type.
485   QualType IntTy = ACtx.IntTy;
486   QualType LongTy = ACtx.LongTy;
487   QualType LongLongTy = ACtx.LongLongTy;
488   QualType SizeTy = ACtx.getSizeType();
489
490   RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
491   RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
492   RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
493
494   // We are finally ready to define specifications for all supported functions.
495   //
496   // The signature needs to have the correct number of arguments.
497   // However, we insert `Irrelevant' when the type is insignificant.
498   //
499   // Argument ranges should always cover all variants. If return value
500   // is completely unknown, omit it from the respective range set.
501   //
502   // All types in the spec need to be canonical.
503   //
504   // Every item in the list of range sets represents a particular
505   // execution path the analyzer would need to explore once
506   // the call is modeled - a new program state is constructed
507   // for every range set, and each range line in the range set
508   // corresponds to a specific constraint within this state.
509   //
510   // Upon comparing to another argument, the other argument is casted
511   // to the current argument's type. This avoids proper promotion but
512   // seems useful. For example, read() receives size_t argument,
513   // and its return value, which is of type ssize_t, cannot be greater
514   // than this argument. If we made a promotion, and the size argument
515   // is equal to, say, 10, then we'd impose a range of [0, 10] on the
516   // return value, however the correct range is [-1, 10].
517   //
518   // Please update the list of functions in the header after editing!
519   //
520   // The format is as follows:
521   //
522   //{ "function name",
523   //  { spec:
524   //    { argument types list, ... },
525   //    return type, purity, { range set list:
526   //      { range list:
527   //        { argument index, within or out of, {{from, to}, ...} },
528   //        { argument index, compares to argument, {{how, which}} },
529   //        ...
530   //      }
531   //    }
532   //  }
533   //}
534
535 #define SUMMARY_WITH_VARIANTS(identifier) {#identifier, {
536 #define END_SUMMARY_WITH_VARIANTS }},
537 #define VARIANT(argument_types, return_type, invalidation_approach)            \
538   { argument_types, return_type, invalidation_approach, {
539 #define END_VARIANT } },
540 #define SUMMARY(identifier, argument_types, return_type,                       \
541                 invalidation_approach)                                         \
542   { #identifier, { { argument_types, return_type, invalidation_approach, {
543 #define END_SUMMARY } } } },
544 #define ARGUMENT_TYPES(...) { __VA_ARGS__ }
545 #define RETURN_TYPE(x) x
546 #define INVALIDATION_APPROACH(x) x
547 #define CASE {
548 #define END_CASE },
549 #define ARGUMENT_CONDITION(argument_number, condition_kind)                    \
550   { argument_number, condition_kind, {
551 #define END_ARGUMENT_CONDITION }},
552 #define RETURN_VALUE_CONDITION(condition_kind)                                 \
553   { Ret, condition_kind, {
554 #define END_RETURN_VALUE_CONDITION }},
555 #define ARG_NO(x) x##U
556 #define RANGE(x, y) { x, y },
557 #define SINGLE_VALUE(x) RANGE(x, x)
558 #define IS_LESS_THAN(arg) { BO_LE, arg }
559
560   FunctionSummaryMap = {
561     // The isascii() family of functions.
562     SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
563             INVALIDATION_APPROACH(EvalCallAsPure))
564       CASE // Boils down to isupper() or islower() or isdigit()
565         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
566           RANGE('0', '9')
567           RANGE('A', 'Z')
568           RANGE('a', 'z')
569         END_ARGUMENT_CONDITION
570         RETURN_VALUE_CONDITION(OutOfRange)
571           SINGLE_VALUE(0)
572         END_RETURN_VALUE_CONDITION
573       END_CASE
574       CASE // The locale-specific range.
575         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
576           RANGE(128, 255)
577         END_ARGUMENT_CONDITION
578         // No post-condition. We are completely unaware of
579         // locale-specific return values.
580       END_CASE
581       CASE
582         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
583           RANGE('0', '9')
584           RANGE('A', 'Z')
585           RANGE('a', 'z')
586           RANGE(128, 255)
587         END_ARGUMENT_CONDITION
588         RETURN_VALUE_CONDITION(WithinRange)
589           SINGLE_VALUE(0)
590         END_RETURN_VALUE_CONDITION
591       END_CASE
592     END_SUMMARY
593     SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
594             INVALIDATION_APPROACH(EvalCallAsPure))
595       CASE // isupper() or islower(). Note that 'Z' is less than 'a'.
596         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
597           RANGE('A', 'Z')
598           RANGE('a', 'z')
599         END_ARGUMENT_CONDITION
600         RETURN_VALUE_CONDITION(OutOfRange)
601           SINGLE_VALUE(0)
602         END_RETURN_VALUE_CONDITION
603       END_CASE
604       CASE // The locale-specific range.
605         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
606           RANGE(128, 255)
607         END_ARGUMENT_CONDITION
608       END_CASE
609       CASE // Other.
610         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
611           RANGE('A', 'Z')
612           RANGE('a', 'z')
613           RANGE(128, 255)
614         END_ARGUMENT_CONDITION
615         RETURN_VALUE_CONDITION(WithinRange)
616           SINGLE_VALUE(0)
617         END_RETURN_VALUE_CONDITION
618       END_CASE
619     END_SUMMARY
620     SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
621             INVALIDATION_APPROACH(EvalCallAsPure))
622       CASE // Is ASCII.
623         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
624           RANGE(0, 127)
625         END_ARGUMENT_CONDITION
626         RETURN_VALUE_CONDITION(OutOfRange)
627           SINGLE_VALUE(0)
628         END_RETURN_VALUE_CONDITION
629       END_CASE
630       CASE
631         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
632           RANGE(0, 127)
633         END_ARGUMENT_CONDITION
634         RETURN_VALUE_CONDITION(WithinRange)
635           SINGLE_VALUE(0)
636         END_RETURN_VALUE_CONDITION
637       END_CASE
638     END_SUMMARY
639     SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
640             INVALIDATION_APPROACH(EvalCallAsPure))
641       CASE
642         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
643           SINGLE_VALUE('\t')
644           SINGLE_VALUE(' ')
645         END_ARGUMENT_CONDITION
646         RETURN_VALUE_CONDITION(OutOfRange)
647           SINGLE_VALUE(0)
648         END_RETURN_VALUE_CONDITION
649       END_CASE
650       CASE
651         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
652           SINGLE_VALUE('\t')
653           SINGLE_VALUE(' ')
654         END_ARGUMENT_CONDITION
655         RETURN_VALUE_CONDITION(WithinRange)
656           SINGLE_VALUE(0)
657         END_RETURN_VALUE_CONDITION
658       END_CASE
659     END_SUMMARY
660     SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
661             INVALIDATION_APPROACH(EvalCallAsPure))
662       CASE // 0..31 or 127
663         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
664           RANGE(0, 32)
665           SINGLE_VALUE(127)
666         END_ARGUMENT_CONDITION
667         RETURN_VALUE_CONDITION(OutOfRange)
668           SINGLE_VALUE(0)
669         END_RETURN_VALUE_CONDITION
670       END_CASE
671       CASE
672         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
673           RANGE(0, 32)
674           SINGLE_VALUE(127)
675         END_ARGUMENT_CONDITION
676         RETURN_VALUE_CONDITION(WithinRange)
677           SINGLE_VALUE(0)
678         END_RETURN_VALUE_CONDITION
679       END_CASE
680     END_SUMMARY
681     SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
682             INVALIDATION_APPROACH(EvalCallAsPure))
683       CASE // Is a digit.
684         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
685           RANGE('0', '9')
686         END_ARGUMENT_CONDITION
687         RETURN_VALUE_CONDITION(OutOfRange)
688           SINGLE_VALUE(0)
689         END_RETURN_VALUE_CONDITION
690       END_CASE
691       CASE
692         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
693           RANGE('0', '9')
694         END_ARGUMENT_CONDITION
695         RETURN_VALUE_CONDITION(WithinRange)
696           SINGLE_VALUE(0)
697         END_RETURN_VALUE_CONDITION
698       END_CASE
699     END_SUMMARY
700     SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
701             INVALIDATION_APPROACH(EvalCallAsPure))
702       CASE
703         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
704           RANGE(33, 126)
705         END_ARGUMENT_CONDITION
706         RETURN_VALUE_CONDITION(OutOfRange)
707           SINGLE_VALUE(0)
708         END_RETURN_VALUE_CONDITION
709       END_CASE
710       CASE
711         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
712           RANGE(33, 126)
713         END_ARGUMENT_CONDITION
714         RETURN_VALUE_CONDITION(WithinRange)
715           SINGLE_VALUE(0)
716         END_RETURN_VALUE_CONDITION
717       END_CASE
718     END_SUMMARY
719     SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
720             INVALIDATION_APPROACH(EvalCallAsPure))
721       CASE // Is certainly lowercase.
722         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
723           RANGE('a', 'z')
724         END_ARGUMENT_CONDITION
725         RETURN_VALUE_CONDITION(OutOfRange)
726           SINGLE_VALUE(0)
727         END_RETURN_VALUE_CONDITION
728       END_CASE
729       CASE // Is ascii but not lowercase.
730         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
731           RANGE(0, 127)
732         END_ARGUMENT_CONDITION
733         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
734           RANGE('a', 'z')
735         END_ARGUMENT_CONDITION
736         RETURN_VALUE_CONDITION(WithinRange)
737           SINGLE_VALUE(0)
738         END_RETURN_VALUE_CONDITION
739       END_CASE
740       CASE // The locale-specific range.
741         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
742           RANGE(128, 255)
743         END_ARGUMENT_CONDITION
744       END_CASE
745       CASE // Is not an unsigned char.
746         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
747           RANGE(0, 255)
748         END_ARGUMENT_CONDITION
749         RETURN_VALUE_CONDITION(WithinRange)
750           SINGLE_VALUE(0)
751         END_RETURN_VALUE_CONDITION
752       END_CASE
753     END_SUMMARY
754     SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
755             INVALIDATION_APPROACH(EvalCallAsPure))
756       CASE
757         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
758           RANGE(32, 126)
759         END_ARGUMENT_CONDITION
760         RETURN_VALUE_CONDITION(OutOfRange)
761           SINGLE_VALUE(0)
762         END_RETURN_VALUE_CONDITION
763       END_CASE
764       CASE
765         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
766           RANGE(32, 126)
767         END_ARGUMENT_CONDITION
768         RETURN_VALUE_CONDITION(WithinRange)
769           SINGLE_VALUE(0)
770         END_RETURN_VALUE_CONDITION
771       END_CASE
772     END_SUMMARY
773     SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
774             INVALIDATION_APPROACH(EvalCallAsPure))
775       CASE
776         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
777           RANGE('!', '/')
778           RANGE(':', '@')
779           RANGE('[', '`')
780           RANGE('{', '~')
781         END_ARGUMENT_CONDITION
782         RETURN_VALUE_CONDITION(OutOfRange)
783           SINGLE_VALUE(0)
784         END_RETURN_VALUE_CONDITION
785       END_CASE
786       CASE
787         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
788           RANGE('!', '/')
789           RANGE(':', '@')
790           RANGE('[', '`')
791           RANGE('{', '~')
792         END_ARGUMENT_CONDITION
793         RETURN_VALUE_CONDITION(WithinRange)
794           SINGLE_VALUE(0)
795         END_RETURN_VALUE_CONDITION
796       END_CASE
797     END_SUMMARY
798     SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
799             INVALIDATION_APPROACH(EvalCallAsPure))
800       CASE // Space, '\f', '\n', '\r', '\t', '\v'.
801         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
802           RANGE(9, 13)
803           SINGLE_VALUE(' ')
804         END_ARGUMENT_CONDITION
805         RETURN_VALUE_CONDITION(OutOfRange)
806           SINGLE_VALUE(0)
807         END_RETURN_VALUE_CONDITION
808       END_CASE
809       CASE // The locale-specific range.
810         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
811           RANGE(128, 255)
812         END_ARGUMENT_CONDITION
813       END_CASE
814       CASE
815         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
816           RANGE(9, 13)
817           SINGLE_VALUE(' ')
818           RANGE(128, 255)
819         END_ARGUMENT_CONDITION
820         RETURN_VALUE_CONDITION(WithinRange)
821           SINGLE_VALUE(0)
822         END_RETURN_VALUE_CONDITION
823       END_CASE
824     END_SUMMARY
825     SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy),
826             INVALIDATION_APPROACH(EvalCallAsPure))
827       CASE // Is certainly uppercase.
828         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
829           RANGE('A', 'Z')
830         END_ARGUMENT_CONDITION
831         RETURN_VALUE_CONDITION(OutOfRange)
832           SINGLE_VALUE(0)
833         END_RETURN_VALUE_CONDITION
834       END_CASE
835       CASE // The locale-specific range.
836         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
837           RANGE(128, 255)
838         END_ARGUMENT_CONDITION
839       END_CASE
840       CASE // Other.
841         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
842           RANGE('A', 'Z') RANGE(128, 255)
843         END_ARGUMENT_CONDITION
844         RETURN_VALUE_CONDITION(WithinRange)
845           SINGLE_VALUE(0)
846         END_RETURN_VALUE_CONDITION
847       END_CASE
848     END_SUMMARY
849     SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
850             INVALIDATION_APPROACH(EvalCallAsPure))
851       CASE
852         ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
853           RANGE('0', '9')
854           RANGE('A', 'F')
855           RANGE('a', 'f')
856         END_ARGUMENT_CONDITION
857         RETURN_VALUE_CONDITION(OutOfRange)
858           SINGLE_VALUE(0)
859         END_RETURN_VALUE_CONDITION
860       END_CASE
861       CASE
862         ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
863           RANGE('0', '9')
864           RANGE('A', 'F')
865           RANGE('a', 'f')
866         END_ARGUMENT_CONDITION
867         RETURN_VALUE_CONDITION(WithinRange)
868           SINGLE_VALUE(0)
869         END_RETURN_VALUE_CONDITION
870       END_CASE
871     END_SUMMARY
872
873     // The getc() family of functions that returns either a char or an EOF.
874     SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
875             INVALIDATION_APPROACH(NoEvalCall))
876       CASE // FIXME: EOF is assumed to be defined as -1.
877         RETURN_VALUE_CONDITION(WithinRange)
878           RANGE(-1, 255)
879         END_RETURN_VALUE_CONDITION
880       END_CASE
881     END_SUMMARY
882     SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
883             INVALIDATION_APPROACH(NoEvalCall))
884       CASE // FIXME: EOF is assumed to be defined as -1.
885         RETURN_VALUE_CONDITION(WithinRange)
886           RANGE(-1, 255)
887         END_RETURN_VALUE_CONDITION
888       END_CASE
889     END_SUMMARY
890     SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy),
891             INVALIDATION_APPROACH(NoEvalCall))
892       CASE // FIXME: EOF is assumed to be defined as -1.
893         RETURN_VALUE_CONDITION(WithinRange)
894           RANGE(-1, 255)
895         END_RETURN_VALUE_CONDITION
896       END_CASE
897     END_SUMMARY
898
899     // read()-like functions that never return more than buffer size.
900     // We are not sure how ssize_t is defined on every platform, so we provide
901     // three variants that should cover common cases.
902     SUMMARY_WITH_VARIANTS(read)
903       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
904               RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
905         CASE
906           RETURN_VALUE_CONDITION(ComparesToArgument)
907             IS_LESS_THAN(ARG_NO(2))
908           END_RETURN_VALUE_CONDITION
909           RETURN_VALUE_CONDITION(WithinRange)
910             RANGE(-1, IntMax)
911           END_RETURN_VALUE_CONDITION
912         END_CASE
913       END_VARIANT
914       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
915               RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
916         CASE
917           RETURN_VALUE_CONDITION(ComparesToArgument)
918             IS_LESS_THAN(ARG_NO(2))
919           END_RETURN_VALUE_CONDITION
920           RETURN_VALUE_CONDITION(WithinRange)
921             RANGE(-1, LongMax)
922           END_RETURN_VALUE_CONDITION
923         END_CASE
924       END_VARIANT
925       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
926               RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
927         CASE
928           RETURN_VALUE_CONDITION(ComparesToArgument)
929             IS_LESS_THAN(ARG_NO(2))
930           END_RETURN_VALUE_CONDITION
931           RETURN_VALUE_CONDITION(WithinRange)
932             RANGE(-1, LongLongMax)
933           END_RETURN_VALUE_CONDITION
934         END_CASE
935       END_VARIANT
936     END_SUMMARY_WITH_VARIANTS
937     SUMMARY_WITH_VARIANTS(write)
938       // Again, due to elusive nature of ssize_t, we have duplicate
939       // our summaries to cover different variants.
940       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
941               RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
942         CASE
943           RETURN_VALUE_CONDITION(ComparesToArgument)
944             IS_LESS_THAN(ARG_NO(2))
945           END_RETURN_VALUE_CONDITION
946           RETURN_VALUE_CONDITION(WithinRange)
947             RANGE(-1, IntMax)
948           END_RETURN_VALUE_CONDITION
949         END_CASE
950       END_VARIANT
951       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
952               RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
953         CASE
954           RETURN_VALUE_CONDITION(ComparesToArgument)
955             IS_LESS_THAN(ARG_NO(2))
956           END_RETURN_VALUE_CONDITION
957           RETURN_VALUE_CONDITION(WithinRange)
958             RANGE(-1, LongMax)
959           END_RETURN_VALUE_CONDITION
960         END_CASE
961       END_VARIANT
962       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
963               RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
964         CASE
965           RETURN_VALUE_CONDITION(ComparesToArgument)
966             IS_LESS_THAN(ARG_NO(2))
967           END_RETURN_VALUE_CONDITION
968           RETURN_VALUE_CONDITION(WithinRange)
969             RANGE(-1, LongLongMax)
970           END_RETURN_VALUE_CONDITION
971         END_CASE
972       END_VARIANT
973     END_SUMMARY_WITH_VARIANTS
974     SUMMARY(fread,
975             ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
976             RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
977       CASE
978         RETURN_VALUE_CONDITION(ComparesToArgument)
979           IS_LESS_THAN(ARG_NO(2))
980         END_RETURN_VALUE_CONDITION
981       END_CASE
982     END_SUMMARY
983     SUMMARY(fwrite,
984             ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
985             RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
986       CASE
987         RETURN_VALUE_CONDITION(ComparesToArgument)
988           IS_LESS_THAN(ARG_NO(2))
989         END_RETURN_VALUE_CONDITION
990       END_CASE
991     END_SUMMARY
992
993     // getline()-like functions either fail or read at least the delimiter.
994     SUMMARY_WITH_VARIANTS(getline)
995       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
996               RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
997         CASE
998           RETURN_VALUE_CONDITION(WithinRange)
999             SINGLE_VALUE(-1)
1000             RANGE(1, IntMax)
1001           END_RETURN_VALUE_CONDITION
1002         END_CASE
1003       END_VARIANT
1004       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1005               RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1006         CASE
1007           RETURN_VALUE_CONDITION(WithinRange)
1008             SINGLE_VALUE(-1)
1009             RANGE(1, LongMax)
1010           END_RETURN_VALUE_CONDITION
1011         END_CASE
1012       END_VARIANT
1013       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1014               RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1015         CASE
1016           RETURN_VALUE_CONDITION(WithinRange)
1017             SINGLE_VALUE(-1)
1018             RANGE(1, LongLongMax)
1019           END_RETURN_VALUE_CONDITION
1020         END_CASE
1021       END_VARIANT
1022     END_SUMMARY_WITH_VARIANTS
1023     SUMMARY_WITH_VARIANTS(getdelim)
1024       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1025             RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
1026         CASE
1027           RETURN_VALUE_CONDITION(WithinRange)
1028             SINGLE_VALUE(-1)
1029             RANGE(1, IntMax)
1030           END_RETURN_VALUE_CONDITION
1031         END_CASE
1032       END_VARIANT
1033       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1034             RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1035         CASE
1036           RETURN_VALUE_CONDITION(WithinRange)
1037             SINGLE_VALUE(-1)
1038             RANGE(1, LongMax)
1039           END_RETURN_VALUE_CONDITION
1040         END_CASE
1041       END_VARIANT
1042       VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1043             RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1044         CASE
1045           RETURN_VALUE_CONDITION(WithinRange)
1046             SINGLE_VALUE(-1)
1047             RANGE(1, LongLongMax)
1048           END_RETURN_VALUE_CONDITION
1049         END_CASE
1050       END_VARIANT
1051     END_SUMMARY_WITH_VARIANTS
1052   };
1053 }
1054
1055 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
1056   // If this checker grows large enough to support C++, Objective-C, or other
1057   // standard libraries, we could use multiple register...Checker() functions,
1058   // which would register various checkers with the help of the same Checker
1059   // class, turning on different function summaries.
1060   mgr.registerChecker<StdLibraryFunctionsChecker>();
1061 }
1062
1063 bool ento::shouldRegisterStdCLibraryFunctionsChecker(const LangOptions &LO) {
1064   return true;
1065 }