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
59using namespace clang;
60using namespace clang::ento;
61
62namespace {
63class 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
225public:
226  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
227  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
228
229private:
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
238ProgramStateRef 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
265ProgramStateRef
266StdLibraryFunctionsChecker::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
316ProgramStateRef
317StdLibraryFunctionsChecker::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
339void 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
370bool 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
403bool 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
431Optional<StdLibraryFunctionsChecker::FunctionSummaryTy>
432StdLibraryFunctionsChecker::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
470void 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
1055void 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
1063bool ento::shouldRegisterStdCLibraryFunctionsChecker(const LangOptions &LO) {
1064  return true;
1065}
1066