xref: /llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp (revision d56a1c68247751e94c4fc46dda282643d3739689)
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 //
11 // This checker provides a specification format - `Summary' - and
12 // contains descriptions of some library functions in this format. Each
13 // specification contains a list of branches for splitting the program state
14 // upon call, and range constraints on argument and return-value symbols that
15 // are satisfied on each branch. This spec can be expanded to include more
16 // items, like external effects of the function.
17 //
18 // The main difference between this approach and the body farms technique is
19 // in more explicit control over how many branches are produced. For example,
20 // consider standard C function `ispunct(int x)', which returns a non-zero value
21 // iff `x' is a punctuation character, that is, when `x' is in range
22 //   ['!', '/']   [':', '@']  U  ['[', '\`']  U  ['{', '~'].
23 // `Summary' provides only two branches for this function. However,
24 // any attempt to describe this range with if-statements in the body farm
25 // would result in many more branches. Because each branch needs to be analyzed
26 // independently, this significantly reduces performance. Additionally,
27 // once we consider a branch on which `x' is in range, say, ['!', '/'],
28 // we assume that such branch is an important separate path through the program,
29 // which may lead to false positives because considering this particular path
30 // was not consciously intended, and therefore it might have been unreachable.
31 //
32 // This checker uses eval::Call for modeling pure functions (functions without
33 // side effets), for which their `Summary' is a precise model. This avoids
34 // unnecessary invalidation passes. Conflicts with other checkers are unlikely
35 // because if the function has no other effects, other checkers would probably
36 // never want to improve upon the modeling done by this checker.
37 //
38 // Non-pure functions, for which only partial improvement over the default
39 // behavior is expected, are modeled via check::PostCall, non-intrusively.
40 //
41 //===----------------------------------------------------------------------===//
42 
43 #include "ErrnoModeling.h"
44 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
45 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
46 #include "clang/StaticAnalyzer/Core/Checker.h"
47 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
48 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
49 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
50 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
51 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
52 #include "llvm/ADT/SmallString.h"
53 #include "llvm/ADT/StringExtras.h"
54 
55 #include <string>
56 
57 using namespace clang;
58 using namespace clang::ento;
59 
60 namespace {
61 class StdLibraryFunctionsChecker
62     : public Checker<check::PreCall, check::PostCall, eval::Call> {
63 
64   class Summary;
65 
66   /// Specify how much the analyzer engine should entrust modeling this function
67   /// to us. If he doesn't, he performs additional invalidations.
68   enum InvalidationKind { NoEvalCall, EvalCallAsPure };
69 
70   // The universal integral type to use in value range descriptions.
71   // Unsigned to make sure overflows are well-defined.
72   typedef uint64_t RangeInt;
73 
74   /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
75   /// a non-negative integer, which less than 5 and not equal to 2. For
76   /// `ComparesToArgument', holds information about how exactly to compare to
77   /// the argument.
78   typedef std::vector<std::pair<RangeInt, RangeInt>> IntRangeVector;
79 
80   /// A reference to an argument or return value by its number.
81   /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
82   /// obviously uint32_t should be enough for all practical purposes.
83   typedef uint32_t ArgNo;
84   static const ArgNo Ret;
85 
86   /// Returns the string representation of an argument index.
87   /// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
88   static SmallString<8> getArgDesc(ArgNo);
89 
90   class ValueConstraint;
91 
92   // Pointer to the ValueConstraint. We need a copyable, polymorphic and
93   // default initialize able type (vector needs that). A raw pointer was good,
94   // however, we cannot default initialize that. unique_ptr makes the Summary
95   // class non-copyable, therefore not an option. Releasing the copyability
96   // requirement would render the initialization of the Summary map infeasible.
97   using ValueConstraintPtr = std::shared_ptr<ValueConstraint>;
98 
99   /// Polymorphic base class that represents a constraint on a given argument
100   /// (or return value) of a function. Derived classes implement different kind
101   /// of constraints, e.g range constraints or correlation between two
102   /// arguments.
103   class ValueConstraint {
104   public:
105     ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {}
106     virtual ~ValueConstraint() {}
107     /// Apply the effects of the constraint on the given program state. If null
108     /// is returned then the constraint is not feasible.
109     virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
110                                   const Summary &Summary,
111                                   CheckerContext &C) const = 0;
112     virtual ValueConstraintPtr negate() const {
113       llvm_unreachable("Not implemented");
114     };
115 
116     // Check whether the constraint is malformed or not. It is malformed if the
117     // specified argument has a mismatch with the given FunctionDecl (e.g. the
118     // arg number is out-of-range of the function's argument list).
119     bool checkValidity(const FunctionDecl *FD) const {
120       const bool ValidArg = ArgN == Ret || ArgN < FD->getNumParams();
121       assert(ValidArg && "Arg out of range!");
122       if (!ValidArg)
123         return false;
124       // Subclasses may further refine the validation.
125       return checkSpecificValidity(FD);
126     }
127     ArgNo getArgNo() const { return ArgN; }
128 
129     // Return those arguments that should be tracked when we report a bug. By
130     // default it is the argument that is constrained, however, in some special
131     // cases we need to track other arguments as well. E.g. a buffer size might
132     // be encoded in another argument.
133     virtual std::vector<ArgNo> getArgsToTrack() const { return {ArgN}; }
134 
135     virtual StringRef getName() const = 0;
136 
137     // Give a description that explains the constraint to the user. Used when
138     // the bug is reported.
139     virtual std::string describe(ProgramStateRef State,
140                                  const Summary &Summary) const {
141       // There are some descendant classes that are not used as argument
142       // constraints, e.g. ComparisonConstraint. In that case we can safely
143       // ignore the implementation of this function.
144       llvm_unreachable("Not implemented");
145     }
146 
147   protected:
148     ArgNo ArgN; // Argument to which we apply the constraint.
149 
150     /// Do polymorphic validation check on the constraint.
151     virtual bool checkSpecificValidity(const FunctionDecl *FD) const {
152       return true;
153     }
154   };
155 
156   /// Given a range, should the argument stay inside or outside this range?
157   enum RangeKind { OutOfRange, WithinRange };
158 
159   /// Encapsulates a range on a single symbol.
160   class RangeConstraint : public ValueConstraint {
161     RangeKind Kind;
162     // A range is formed as a set of intervals (sub-ranges).
163     // E.g. {['A', 'Z'], ['a', 'z']}
164     //
165     // The default constructed RangeConstraint has an empty range set, applying
166     // such constraint does not involve any assumptions, thus the State remains
167     // unchanged. This is meaningful, if the range is dependent on a looked up
168     // type (e.g. [0, Socklen_tMax]). If the type is not found, then the range
169     // is default initialized to be empty.
170     IntRangeVector Ranges;
171 
172   public:
173     StringRef getName() const override { return "Range"; }
174     RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges)
175         : ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {}
176 
177     std::string describe(ProgramStateRef State,
178                          const Summary &Summary) const override;
179 
180     const IntRangeVector &getRanges() const { return Ranges; }
181 
182   private:
183     ProgramStateRef applyAsOutOfRange(ProgramStateRef State,
184                                       const CallEvent &Call,
185                                       const Summary &Summary) const;
186     ProgramStateRef applyAsWithinRange(ProgramStateRef State,
187                                        const CallEvent &Call,
188                                        const Summary &Summary) const;
189 
190   public:
191     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
192                           const Summary &Summary,
193                           CheckerContext &C) const override {
194       switch (Kind) {
195       case OutOfRange:
196         return applyAsOutOfRange(State, Call, Summary);
197       case WithinRange:
198         return applyAsWithinRange(State, Call, Summary);
199       }
200       llvm_unreachable("Unknown range kind!");
201     }
202 
203     ValueConstraintPtr negate() const override {
204       RangeConstraint Tmp(*this);
205       switch (Kind) {
206       case OutOfRange:
207         Tmp.Kind = WithinRange;
208         break;
209       case WithinRange:
210         Tmp.Kind = OutOfRange;
211         break;
212       }
213       return std::make_shared<RangeConstraint>(Tmp);
214     }
215 
216     bool checkSpecificValidity(const FunctionDecl *FD) const override {
217       const bool ValidArg =
218           getArgType(FD, ArgN)->isIntegralType(FD->getASTContext());
219       assert(ValidArg &&
220              "This constraint should be applied on an integral type");
221       return ValidArg;
222     }
223   };
224 
225   class ComparisonConstraint : public ValueConstraint {
226     BinaryOperator::Opcode Opcode;
227     ArgNo OtherArgN;
228 
229   public:
230     StringRef getName() const override { return "Comparison"; };
231     ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode,
232                          ArgNo OtherArgN)
233         : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {}
234     ArgNo getOtherArgNo() const { return OtherArgN; }
235     BinaryOperator::Opcode getOpcode() const { return Opcode; }
236     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
237                           const Summary &Summary,
238                           CheckerContext &C) const override;
239   };
240 
241   class NotNullConstraint : public ValueConstraint {
242     using ValueConstraint::ValueConstraint;
243     // This variable has a role when we negate the constraint.
244     bool CannotBeNull = true;
245 
246   public:
247     std::string describe(ProgramStateRef State,
248                          const Summary &Summary) const override;
249     StringRef getName() const override { return "NonNull"; }
250     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
251                           const Summary &Summary,
252                           CheckerContext &C) const override {
253       SVal V = getArgSVal(Call, getArgNo());
254       if (V.isUndef())
255         return State;
256 
257       DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>();
258       if (!isa<Loc>(L))
259         return State;
260 
261       return State->assume(L, CannotBeNull);
262     }
263 
264     ValueConstraintPtr negate() const override {
265       NotNullConstraint Tmp(*this);
266       Tmp.CannotBeNull = !this->CannotBeNull;
267       return std::make_shared<NotNullConstraint>(Tmp);
268     }
269 
270     bool checkSpecificValidity(const FunctionDecl *FD) const override {
271       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
272       assert(ValidArg &&
273              "This constraint should be applied only on a pointer type");
274       return ValidArg;
275     }
276   };
277 
278   // Represents a buffer argument with an additional size constraint. The
279   // constraint may be a concrete value, or a symbolic value in an argument.
280   // Example 1. Concrete value as the minimum buffer size.
281   //   char *asctime_r(const struct tm *restrict tm, char *restrict buf);
282   //   // `buf` size must be at least 26 bytes according the POSIX standard.
283   // Example 2. Argument as a buffer size.
284   //   ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
285   // Example 3. The size is computed as a multiplication of other args.
286   //   size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
287   //   // Here, ptr is the buffer, and its minimum size is `size * nmemb`.
288   class BufferSizeConstraint : public ValueConstraint {
289     // The concrete value which is the minimum size for the buffer.
290     llvm::Optional<llvm::APSInt> ConcreteSize;
291     // The argument which holds the size of the buffer.
292     llvm::Optional<ArgNo> SizeArgN;
293     // The argument which is a multiplier to size. This is set in case of
294     // `fread` like functions where the size is computed as a multiplication of
295     // two arguments.
296     llvm::Optional<ArgNo> SizeMultiplierArgN;
297     // The operator we use in apply. This is negated in negate().
298     BinaryOperator::Opcode Op = BO_LE;
299 
300   public:
301     StringRef getName() const override { return "BufferSize"; }
302     BufferSizeConstraint(ArgNo Buffer, llvm::APSInt BufMinSize)
303         : ValueConstraint(Buffer), ConcreteSize(BufMinSize) {}
304     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize)
305         : ValueConstraint(Buffer), SizeArgN(BufSize) {}
306     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier)
307         : ValueConstraint(Buffer), SizeArgN(BufSize),
308           SizeMultiplierArgN(BufSizeMultiplier) {}
309 
310     std::vector<ArgNo> getArgsToTrack() const override {
311       std::vector<ArgNo> Result{ArgN};
312       if (SizeArgN)
313         Result.push_back(*SizeArgN);
314       if (SizeMultiplierArgN)
315         Result.push_back(*SizeMultiplierArgN);
316       return Result;
317     }
318 
319     std::string describe(ProgramStateRef State,
320                          const Summary &Summary) const override;
321 
322     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
323                           const Summary &Summary,
324                           CheckerContext &C) const override {
325       SValBuilder &SvalBuilder = C.getSValBuilder();
326       // The buffer argument.
327       SVal BufV = getArgSVal(Call, getArgNo());
328 
329       // Get the size constraint.
330       const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() {
331         if (ConcreteSize) {
332           return SVal(SvalBuilder.makeIntVal(*ConcreteSize));
333         }
334         assert(SizeArgN && "The constraint must be either a concrete value or "
335                            "encoded in an argument.");
336         // The size argument.
337         SVal SizeV = getArgSVal(Call, *SizeArgN);
338         // Multiply with another argument if given.
339         if (SizeMultiplierArgN) {
340           SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
341           SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
342                                         Summary.getArgType(*SizeArgN));
343         }
344         return SizeV;
345       }();
346 
347       // The dynamic size of the buffer argument, got from the analyzer engine.
348       SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
349 
350       SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize,
351                                             SvalBuilder.getContext().BoolTy);
352       if (auto F = Feasible.getAs<DefinedOrUnknownSVal>())
353         return State->assume(*F, true);
354 
355       // We can get here only if the size argument or the dynamic size is
356       // undefined. But the dynamic size should never be undefined, only
357       // unknown. So, here, the size of the argument is undefined, i.e. we
358       // cannot apply the constraint. Actually, other checkers like
359       // CallAndMessage should catch this situation earlier, because we call a
360       // function with an uninitialized argument.
361       llvm_unreachable("Size argument or the dynamic size is Undefined");
362     }
363 
364     ValueConstraintPtr negate() const override {
365       BufferSizeConstraint Tmp(*this);
366       Tmp.Op = BinaryOperator::negateComparisonOp(Op);
367       return std::make_shared<BufferSizeConstraint>(Tmp);
368     }
369 
370     bool checkSpecificValidity(const FunctionDecl *FD) const override {
371       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
372       assert(ValidArg &&
373              "This constraint should be applied only on a pointer type");
374       return ValidArg;
375     }
376   };
377 
378   /// The complete list of constraints that defines a single branch.
379   using ConstraintSet = std::vector<ValueConstraintPtr>;
380 
381   /// Define how a function affects the system variable 'errno'.
382   /// This works together with the \c ErrnoModeling and \c ErrnoChecker classes.
383   /// Currently 3 use cases exist: success, failure, irrelevant.
384   /// In the future the failure case can be customized to set \c errno to a
385   /// more specific constraint (for example > 0), or new case can be added
386   /// for functions which require check of \c errno in both success and failure
387   /// case.
388   class ErrnoConstraintBase {
389   public:
390     /// Apply specific state changes related to the errno variable.
391     virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
392                                   const Summary &Summary,
393                                   CheckerContext &C) const = 0;
394     /// Get a NoteTag about the changes made to 'errno' and the possible bug.
395     /// It may return \c nullptr (if no bug report from \c ErrnoChecker is
396     /// expected).
397     virtual const NoteTag *describe(CheckerContext &C,
398                                     StringRef FunctionName) const {
399       return nullptr;
400     }
401 
402     virtual ~ErrnoConstraintBase() {}
403 
404   protected:
405     ErrnoConstraintBase() = default;
406 
407     /// This is used for conjure symbol for errno to differentiate from the
408     /// original call expression (same expression is used for the errno symbol).
409     static int Tag;
410   };
411 
412   /// Set errno constraint at failure cases of standard functions.
413   /// Failure case: 'errno' becomes not equal to 0 and may or may not be checked
414   /// by the program. \c ErrnoChecker does not emit a bug report after such a
415   /// function call.
416   class FailureErrnoConstraint : public ErrnoConstraintBase {
417   public:
418     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
419                           const Summary &Summary,
420                           CheckerContext &C) const override {
421       SValBuilder &SVB = C.getSValBuilder();
422       NonLoc ErrnoSVal =
423           SVB.conjureSymbolVal(&Tag, Call.getOriginExpr(),
424                                C.getLocationContext(), C.getASTContext().IntTy,
425                                C.blockCount())
426               .castAs<NonLoc>();
427       return errno_modeling::setErrnoForStdFailure(State, C, ErrnoSVal);
428     }
429   };
430 
431   /// Set errno constraint at success cases of standard functions.
432   /// Success case: 'errno' is not allowed to be used.
433   /// \c ErrnoChecker can emit bug report after such a function call if errno
434   /// is used.
435   class SuccessErrnoConstraint : public ErrnoConstraintBase {
436   public:
437     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
438                           const Summary &Summary,
439                           CheckerContext &C) const override {
440       return errno_modeling::setErrnoForStdSuccess(State, C);
441     }
442 
443     const NoteTag *describe(CheckerContext &C,
444                             StringRef FunctionName) const override {
445       return errno_modeling::getNoteTagForStdSuccess(C, FunctionName);
446     }
447   };
448 
449   /// Set errno constraints if use of 'errno' is irrelevant to the
450   /// modeled function or modeling is not possible.
451   class NoErrnoConstraint : public ErrnoConstraintBase {
452   public:
453     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
454                           const Summary &Summary,
455                           CheckerContext &C) const override {
456       return errno_modeling::setErrnoState(State, errno_modeling::Irrelevant);
457     }
458   };
459 
460   /// A single branch of a function summary.
461   ///
462   /// A branch is defined by a series of constraints - "assumptions" -
463   /// that together form a single possible outcome of invoking the function.
464   /// When static analyzer considers a branch, it tries to introduce
465   /// a child node in the Exploded Graph. The child node has to include
466   /// constraints that define the branch. If the constraints contradict
467   /// existing constraints in the state, the node is not created and the branch
468   /// is dropped; otherwise it's queued for future exploration.
469   /// The branch is accompanied by a note text that may be displayed
470   /// to the user when a bug is found on a path that takes this branch.
471   ///
472   /// For example, consider the branches in `isalpha(x)`:
473   ///   Branch 1)
474   ///     x is in range ['A', 'Z'] or in ['a', 'z']
475   ///     then the return value is not 0. (I.e. out-of-range [0, 0])
476   ///     and the note may say "Assuming the character is alphabetical"
477   ///   Branch 2)
478   ///     x is out-of-range ['A', 'Z'] and out-of-range ['a', 'z']
479   ///     then the return value is 0
480   ///     and the note may say "Assuming the character is non-alphabetical".
481   class SummaryCase {
482     ConstraintSet Constraints;
483     const ErrnoConstraintBase &ErrnoConstraint;
484     StringRef Note;
485 
486   public:
487     SummaryCase(ConstraintSet &&Constraints, const ErrnoConstraintBase &ErrnoC,
488                 StringRef Note)
489         : Constraints(std::move(Constraints)), ErrnoConstraint(ErrnoC),
490           Note(Note) {}
491 
492     SummaryCase(const ConstraintSet &Constraints,
493                 const ErrnoConstraintBase &ErrnoC, StringRef Note)
494         : Constraints(Constraints), ErrnoConstraint(ErrnoC), Note(Note) {}
495 
496     const ConstraintSet &getConstraints() const { return Constraints; }
497     const ErrnoConstraintBase &getErrnoConstraint() const {
498       return ErrnoConstraint;
499     }
500     StringRef getNote() const { return Note; }
501   };
502 
503   using ArgTypes = std::vector<Optional<QualType>>;
504   using RetType = Optional<QualType>;
505 
506   // A placeholder type, we use it whenever we do not care about the concrete
507   // type in a Signature.
508   const QualType Irrelevant{};
509   bool static isIrrelevant(QualType T) { return T.isNull(); }
510 
511   // The signature of a function we want to describe with a summary. This is a
512   // concessive signature, meaning there may be irrelevant types in the
513   // signature which we do not check against a function with concrete types.
514   // All types in the spec need to be canonical.
515   class Signature {
516     using ArgQualTypes = std::vector<QualType>;
517     ArgQualTypes ArgTys;
518     QualType RetTy;
519     // True if any component type is not found by lookup.
520     bool Invalid = false;
521 
522   public:
523     // Construct a signature from optional types. If any of the optional types
524     // are not set then the signature will be invalid.
525     Signature(ArgTypes ArgTys, RetType RetTy) {
526       for (Optional<QualType> Arg : ArgTys) {
527         if (!Arg) {
528           Invalid = true;
529           return;
530         } else {
531           assertArgTypeSuitableForSignature(*Arg);
532           this->ArgTys.push_back(*Arg);
533         }
534       }
535       if (!RetTy) {
536         Invalid = true;
537         return;
538       } else {
539         assertRetTypeSuitableForSignature(*RetTy);
540         this->RetTy = *RetTy;
541       }
542     }
543 
544     bool isInvalid() const { return Invalid; }
545     bool matches(const FunctionDecl *FD) const;
546 
547   private:
548     static void assertArgTypeSuitableForSignature(QualType T) {
549       assert((T.isNull() || !T->isVoidType()) &&
550              "We should have no void types in the spec");
551       assert((T.isNull() || T.isCanonical()) &&
552              "We should only have canonical types in the spec");
553     }
554     static void assertRetTypeSuitableForSignature(QualType T) {
555       assert((T.isNull() || T.isCanonical()) &&
556              "We should only have canonical types in the spec");
557     }
558   };
559 
560   static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) {
561     assert(FD && "Function must be set");
562     QualType T = (ArgN == Ret)
563                      ? FD->getReturnType().getCanonicalType()
564                      : FD->getParamDecl(ArgN)->getType().getCanonicalType();
565     return T;
566   }
567 
568   using SummaryCases = std::vector<SummaryCase>;
569 
570   /// A summary includes information about
571   ///   * function prototype (signature)
572   ///   * approach to invalidation,
573   ///   * a list of branches - so, a list of list of ranges,
574   ///   * a list of argument constraints, that must be true on every branch.
575   ///     If these constraints are not satisfied that means a fatal error
576   ///     usually resulting in undefined behaviour.
577   ///
578   /// Application of a summary:
579   ///   The signature and argument constraints together contain information
580   ///   about which functions are handled by the summary. The signature can use
581   ///   "wildcards", i.e. Irrelevant types. Irrelevant type of a parameter in
582   ///   a signature means that type is not compared to the type of the parameter
583   ///   in the found FunctionDecl. Argument constraints may specify additional
584   ///   rules for the given parameter's type, those rules are checked once the
585   ///   signature is matched.
586   class Summary {
587     const InvalidationKind InvalidationKd;
588     SummaryCases Cases;
589     ConstraintSet ArgConstraints;
590 
591     // The function to which the summary applies. This is set after lookup and
592     // match to the signature.
593     const FunctionDecl *FD = nullptr;
594 
595   public:
596     Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {}
597 
598     Summary &Case(ConstraintSet &&CS, const ErrnoConstraintBase &ErrnoC,
599                   StringRef Note = "") {
600       Cases.push_back(SummaryCase(std::move(CS), ErrnoC, Note));
601       return *this;
602     }
603     Summary &Case(const ConstraintSet &CS, const ErrnoConstraintBase &ErrnoC,
604                   StringRef Note = "") {
605       Cases.push_back(SummaryCase(CS, ErrnoC, Note));
606       return *this;
607     }
608     Summary &ArgConstraint(ValueConstraintPtr VC) {
609       assert(VC->getArgNo() != Ret &&
610              "Arg constraint should not refer to the return value");
611       ArgConstraints.push_back(VC);
612       return *this;
613     }
614 
615     InvalidationKind getInvalidationKd() const { return InvalidationKd; }
616     const SummaryCases &getCases() const { return Cases; }
617     const ConstraintSet &getArgConstraints() const { return ArgConstraints; }
618 
619     QualType getArgType(ArgNo ArgN) const {
620       return StdLibraryFunctionsChecker::getArgType(FD, ArgN);
621     }
622 
623     // Returns true if the summary should be applied to the given function.
624     // And if yes then store the function declaration.
625     bool matchesAndSet(const Signature &Sign, const FunctionDecl *FD) {
626       bool Result = Sign.matches(FD) && validateByConstraints(FD);
627       if (Result) {
628         assert(!this->FD && "FD must not be set more than once");
629         this->FD = FD;
630       }
631       return Result;
632     }
633 
634   private:
635     // Once we know the exact type of the function then do validation check on
636     // all the given constraints.
637     bool validateByConstraints(const FunctionDecl *FD) const {
638       for (const SummaryCase &Case : Cases)
639         for (const ValueConstraintPtr &Constraint : Case.getConstraints())
640           if (!Constraint->checkValidity(FD))
641             return false;
642       for (const ValueConstraintPtr &Constraint : ArgConstraints)
643         if (!Constraint->checkValidity(FD))
644           return false;
645       return true;
646     }
647   };
648 
649   // The map of all functions supported by the checker. It is initialized
650   // lazily, and it doesn't change after initialization.
651   using FunctionSummaryMapType = llvm::DenseMap<const FunctionDecl *, Summary>;
652   mutable FunctionSummaryMapType FunctionSummaryMap;
653 
654   mutable std::unique_ptr<BugType> BT_InvalidArg;
655   mutable bool SummariesInitialized = false;
656 
657   static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) {
658     return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN);
659   }
660 
661 public:
662   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
663   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
664   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
665 
666   enum CheckKind {
667     CK_StdCLibraryFunctionArgsChecker,
668     CK_StdCLibraryFunctionsTesterChecker,
669     CK_NumCheckKinds
670   };
671   bool ChecksEnabled[CK_NumCheckKinds] = {false};
672   CheckerNameRef CheckNames[CK_NumCheckKinds];
673 
674   bool DisplayLoadedSummaries = false;
675   bool ModelPOSIX = false;
676   bool ShouldAssumeControlledEnvironment = false;
677 
678 private:
679   Optional<Summary> findFunctionSummary(const FunctionDecl *FD,
680                                         CheckerContext &C) const;
681   Optional<Summary> findFunctionSummary(const CallEvent &Call,
682                                         CheckerContext &C) const;
683 
684   void initFunctionSummaries(CheckerContext &C) const;
685 
686   void reportBug(const CallEvent &Call, ExplodedNode *N,
687                  const ValueConstraint *VC, const Summary &Summary,
688                  CheckerContext &C) const {
689     if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
690       return;
691     std::string Msg =
692         (Twine("Function argument constraint is not satisfied, constraint: ") +
693          VC->getName().data())
694             .str();
695     if (!BT_InvalidArg)
696       BT_InvalidArg = std::make_unique<BugType>(
697           CheckNames[CK_StdCLibraryFunctionArgsChecker],
698           "Unsatisfied argument constraints", categories::LogicError);
699     auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
700 
701     for (ArgNo ArgN : VC->getArgsToTrack())
702       bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
703 
704     // Highlight the range of the argument that was violated.
705     R->addRange(Call.getArgSourceRange(VC->getArgNo()));
706 
707     // Describe the argument constraint in a note.
708     R->addNote(VC->describe(C.getState(), Summary), R->getLocation(),
709                Call.getArgSourceRange(VC->getArgNo()));
710 
711     C.emitReport(std::move(R));
712   }
713 
714   /// These are the errno constraints that can be passed to summary cases.
715   /// One of these should fit for a single summary case.
716   /// Usually if a failure return value exists for function, that function
717   /// needs different cases for success and failure with different errno
718   /// constraints (and different return value constraints).
719   const NoErrnoConstraint ErrnoIrrelevant{};
720   const SuccessErrnoConstraint ErrnoMustNotBeChecked{};
721   const FailureErrnoConstraint ErrnoNEZeroIrrelevant{};
722 };
723 
724 int StdLibraryFunctionsChecker::ErrnoConstraintBase::Tag = 0;
725 
726 const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret =
727     std::numeric_limits<ArgNo>::max();
728 
729 } // end of anonymous namespace
730 
731 static BasicValueFactory &getBVF(ProgramStateRef State) {
732   ProgramStateManager &Mgr = State->getStateManager();
733   SValBuilder &SVB = Mgr.getSValBuilder();
734   return SVB.getBasicValueFactory();
735 }
736 
737 std::string StdLibraryFunctionsChecker::NotNullConstraint::describe(
738     ProgramStateRef State, const Summary &Summary) const {
739   SmallString<48> Result;
740   Result += "The ";
741   Result += getArgDesc(ArgN);
742   Result += " should not be NULL";
743   return Result.c_str();
744 }
745 
746 std::string StdLibraryFunctionsChecker::RangeConstraint::describe(
747     ProgramStateRef State, const Summary &Summary) const {
748 
749   BasicValueFactory &BVF = getBVF(State);
750 
751   QualType T = Summary.getArgType(getArgNo());
752   SmallString<48> Result;
753   Result += "The ";
754   Result += getArgDesc(ArgN);
755   Result += " should be ";
756 
757   // Range kind as a string.
758   Kind == OutOfRange ? Result += "out of" : Result += "within";
759 
760   // Get the range values as a string.
761   Result += " the range ";
762   if (Ranges.size() > 1)
763     Result += "[";
764   unsigned I = Ranges.size();
765   for (const std::pair<RangeInt, RangeInt> &R : Ranges) {
766     Result += "[";
767     const llvm::APSInt &Min = BVF.getValue(R.first, T);
768     const llvm::APSInt &Max = BVF.getValue(R.second, T);
769     Min.toString(Result);
770     Result += ", ";
771     Max.toString(Result);
772     Result += "]";
773     if (--I > 0)
774       Result += ", ";
775   }
776   if (Ranges.size() > 1)
777     Result += "]";
778 
779   return Result.c_str();
780 }
781 
782 SmallString<8>
783 StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) {
784   SmallString<8> Result;
785   Result += std::to_string(ArgN + 1);
786   Result += llvm::getOrdinalSuffix(ArgN + 1);
787   Result += " arg";
788   return Result;
789 }
790 
791 std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
792     ProgramStateRef State, const Summary &Summary) const {
793   SmallString<96> Result;
794   Result += "The size of the ";
795   Result += getArgDesc(ArgN);
796   Result += " should be equal to or less than the value of ";
797   if (ConcreteSize) {
798     ConcreteSize->toString(Result);
799   } else if (SizeArgN) {
800     Result += "the ";
801     Result += getArgDesc(*SizeArgN);
802     if (SizeMultiplierArgN) {
803       Result += " times the ";
804       Result += getArgDesc(*SizeMultiplierArgN);
805     }
806   }
807   return Result.c_str();
808 }
809 
810 ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange(
811     ProgramStateRef State, const CallEvent &Call,
812     const Summary &Summary) const {
813   if (Ranges.empty())
814     return State;
815 
816   ProgramStateManager &Mgr = State->getStateManager();
817   SValBuilder &SVB = Mgr.getSValBuilder();
818   BasicValueFactory &BVF = SVB.getBasicValueFactory();
819   ConstraintManager &CM = Mgr.getConstraintManager();
820   QualType T = Summary.getArgType(getArgNo());
821   SVal V = getArgSVal(Call, getArgNo());
822 
823   if (auto N = V.getAs<NonLoc>()) {
824     const IntRangeVector &R = getRanges();
825     size_t E = R.size();
826     for (size_t I = 0; I != E; ++I) {
827       const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
828       const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
829       assert(Min <= Max);
830       State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
831       if (!State)
832         break;
833     }
834   }
835 
836   return State;
837 }
838 
839 ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange(
840     ProgramStateRef State, const CallEvent &Call,
841     const Summary &Summary) const {
842   if (Ranges.empty())
843     return State;
844 
845   ProgramStateManager &Mgr = State->getStateManager();
846   SValBuilder &SVB = Mgr.getSValBuilder();
847   BasicValueFactory &BVF = SVB.getBasicValueFactory();
848   ConstraintManager &CM = Mgr.getConstraintManager();
849   QualType T = Summary.getArgType(getArgNo());
850   SVal V = getArgSVal(Call, getArgNo());
851 
852   // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
853   // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
854   // and then cut away all holes in R one by one.
855   //
856   // E.g. consider a range list R as [A, B] and [C, D]
857   // -------+--------+------------------+------------+----------->
858   //        A        B                  C            D
859   // Then we assume that the value is not in [-inf, A - 1],
860   // then not in [D + 1, +inf], then not in [B + 1, C - 1]
861   if (auto N = V.getAs<NonLoc>()) {
862     const IntRangeVector &R = getRanges();
863     size_t E = R.size();
864 
865     const llvm::APSInt &MinusInf = BVF.getMinValue(T);
866     const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
867 
868     const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
869     if (Left != PlusInf) {
870       assert(MinusInf <= Left);
871       State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
872       if (!State)
873         return nullptr;
874     }
875 
876     const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
877     if (Right != MinusInf) {
878       assert(Right <= PlusInf);
879       State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
880       if (!State)
881         return nullptr;
882     }
883 
884     for (size_t I = 1; I != E; ++I) {
885       const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
886       const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
887       if (Min <= Max) {
888         State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
889         if (!State)
890           return nullptr;
891       }
892     }
893   }
894 
895   return State;
896 }
897 
898 ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply(
899     ProgramStateRef State, const CallEvent &Call, const Summary &Summary,
900     CheckerContext &C) const {
901 
902   ProgramStateManager &Mgr = State->getStateManager();
903   SValBuilder &SVB = Mgr.getSValBuilder();
904   QualType CondT = SVB.getConditionType();
905   QualType T = Summary.getArgType(getArgNo());
906   SVal V = getArgSVal(Call, getArgNo());
907 
908   BinaryOperator::Opcode Op = getOpcode();
909   ArgNo OtherArg = getOtherArgNo();
910   SVal OtherV = getArgSVal(Call, OtherArg);
911   QualType OtherT = Summary.getArgType(OtherArg);
912   // Note: we avoid integral promotion for comparison.
913   OtherV = SVB.evalCast(OtherV, T, OtherT);
914   if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
915                        .getAs<DefinedOrUnknownSVal>())
916     State = State->assume(*CompV, true);
917   return State;
918 }
919 
920 void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
921                                               CheckerContext &C) const {
922   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
923   if (!FoundSummary)
924     return;
925 
926   const Summary &Summary = *FoundSummary;
927   ProgramStateRef State = C.getState();
928 
929   ProgramStateRef NewState = State;
930   for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) {
931     ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C);
932     ProgramStateRef FailureSt =
933         Constraint->negate()->apply(NewState, Call, Summary, C);
934     // The argument constraint is not satisfied.
935     if (FailureSt && !SuccessSt) {
936       if (ExplodedNode *N = C.generateErrorNode(NewState))
937         reportBug(Call, N, Constraint.get(), Summary, C);
938       break;
939     } else {
940       // We will apply the constraint even if we cannot reason about the
941       // argument. This means both SuccessSt and FailureSt can be true. If we
942       // weren't applying the constraint that would mean that symbolic
943       // execution continues on a code whose behaviour is undefined.
944       assert(SuccessSt);
945       NewState = SuccessSt;
946     }
947   }
948   if (NewState && NewState != State)
949     C.addTransition(NewState);
950 }
951 
952 void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
953                                                CheckerContext &C) const {
954   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
955   if (!FoundSummary)
956     return;
957 
958   // Now apply the constraints.
959   const Summary &Summary = *FoundSummary;
960   ProgramStateRef State = C.getState();
961   const ExplodedNode *Node = C.getPredecessor();
962 
963   // Apply case/branch specifications.
964   for (const SummaryCase &Case : Summary.getCases()) {
965     ProgramStateRef NewState = State;
966     for (const ValueConstraintPtr &Constraint : Case.getConstraints()) {
967       NewState = Constraint->apply(NewState, Call, Summary, C);
968       if (!NewState)
969         break;
970     }
971 
972     if (NewState)
973       NewState = Case.getErrnoConstraint().apply(NewState, Call, Summary, C);
974 
975     if (NewState && NewState != State) {
976       if (Case.getNote().empty()) {
977         const NoteTag *NT = nullptr;
978         if (const auto *D = dyn_cast_or_null<FunctionDecl>(Call.getDecl()))
979           NT = Case.getErrnoConstraint().describe(C, D->getNameAsString());
980         C.addTransition(NewState, NT);
981       } else {
982         StringRef Note = Case.getNote();
983         const NoteTag *Tag = C.getNoteTag(
984             // Sorry couldn't help myself.
985             [Node, Note]() -> std::string {
986               // Don't emit "Assuming..." note when we ended up
987               // knowing in advance which branch is taken.
988               return (Node->succ_size() > 1) ? Note.str() : "";
989             },
990             /*IsPrunable=*/true);
991         C.addTransition(NewState, Tag);
992       }
993     }
994   }
995 }
996 
997 bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
998                                           CheckerContext &C) const {
999   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
1000   if (!FoundSummary)
1001     return false;
1002 
1003   const Summary &Summary = *FoundSummary;
1004   switch (Summary.getInvalidationKd()) {
1005   case EvalCallAsPure: {
1006     ProgramStateRef State = C.getState();
1007     const LocationContext *LC = C.getLocationContext();
1008     const auto *CE = cast<CallExpr>(Call.getOriginExpr());
1009     SVal V = C.getSValBuilder().conjureSymbolVal(
1010         CE, LC, CE->getType().getCanonicalType(), C.blockCount());
1011     State = State->BindExpr(CE, LC, V);
1012 
1013     C.addTransition(State);
1014 
1015     return true;
1016   }
1017   case NoEvalCall:
1018     // Summary tells us to avoid performing eval::Call. The function is possibly
1019     // evaluated by another checker, or evaluated conservatively.
1020     return false;
1021   }
1022   llvm_unreachable("Unknown invalidation kind!");
1023 }
1024 
1025 bool StdLibraryFunctionsChecker::Signature::matches(
1026     const FunctionDecl *FD) const {
1027   assert(!isInvalid());
1028   // Check the number of arguments.
1029   if (FD->param_size() != ArgTys.size())
1030     return false;
1031 
1032   // The "restrict" keyword is illegal in C++, however, many libc
1033   // implementations use the "__restrict" compiler intrinsic in functions
1034   // prototypes. The "__restrict" keyword qualifies a type as a restricted type
1035   // even in C++.
1036   // In case of any non-C99 languages, we don't want to match based on the
1037   // restrict qualifier because we cannot know if the given libc implementation
1038   // qualifies the paramter type or not.
1039   auto RemoveRestrict = [&FD](QualType T) {
1040     if (!FD->getASTContext().getLangOpts().C99)
1041       T.removeLocalRestrict();
1042     return T;
1043   };
1044 
1045   // Check the return type.
1046   if (!isIrrelevant(RetTy)) {
1047     QualType FDRetTy = RemoveRestrict(FD->getReturnType().getCanonicalType());
1048     if (RetTy != FDRetTy)
1049       return false;
1050   }
1051 
1052   // Check the argument types.
1053   for (size_t I = 0, E = ArgTys.size(); I != E; ++I) {
1054     QualType ArgTy = ArgTys[I];
1055     if (isIrrelevant(ArgTy))
1056       continue;
1057     QualType FDArgTy =
1058         RemoveRestrict(FD->getParamDecl(I)->getType().getCanonicalType());
1059     if (ArgTy != FDArgTy)
1060       return false;
1061   }
1062 
1063   return true;
1064 }
1065 
1066 Optional<StdLibraryFunctionsChecker::Summary>
1067 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
1068                                                 CheckerContext &C) const {
1069   if (!FD)
1070     return None;
1071 
1072   initFunctionSummaries(C);
1073 
1074   auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl());
1075   if (FSMI == FunctionSummaryMap.end())
1076     return None;
1077   return FSMI->second;
1078 }
1079 
1080 Optional<StdLibraryFunctionsChecker::Summary>
1081 StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call,
1082                                                 CheckerContext &C) const {
1083   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
1084   if (!FD)
1085     return None;
1086   return findFunctionSummary(FD, C);
1087 }
1088 
1089 void StdLibraryFunctionsChecker::initFunctionSummaries(
1090     CheckerContext &C) const {
1091   if (SummariesInitialized)
1092     return;
1093 
1094   SValBuilder &SVB = C.getSValBuilder();
1095   BasicValueFactory &BVF = SVB.getBasicValueFactory();
1096   const ASTContext &ACtx = BVF.getContext();
1097 
1098   // Helper class to lookup a type by its name.
1099   class LookupType {
1100     const ASTContext &ACtx;
1101 
1102   public:
1103     LookupType(const ASTContext &ACtx) : ACtx(ACtx) {}
1104 
1105     // Find the type. If not found then the optional is not set.
1106     llvm::Optional<QualType> operator()(StringRef Name) {
1107       IdentifierInfo &II = ACtx.Idents.get(Name);
1108       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
1109       if (LookupRes.empty())
1110         return None;
1111 
1112       // Prioritze typedef declarations.
1113       // This is needed in case of C struct typedefs. E.g.:
1114       //   typedef struct FILE FILE;
1115       // In this case, we have a RecordDecl 'struct FILE' with the name 'FILE'
1116       // and we have a TypedefDecl with the name 'FILE'.
1117       for (Decl *D : LookupRes)
1118         if (auto *TD = dyn_cast<TypedefNameDecl>(D))
1119           return ACtx.getTypeDeclType(TD).getCanonicalType();
1120 
1121       // Find the first TypeDecl.
1122       // There maybe cases when a function has the same name as a struct.
1123       // E.g. in POSIX: `struct stat` and the function `stat()`:
1124       //   int stat(const char *restrict path, struct stat *restrict buf);
1125       for (Decl *D : LookupRes)
1126         if (auto *TD = dyn_cast<TypeDecl>(D))
1127           return ACtx.getTypeDeclType(TD).getCanonicalType();
1128       return None;
1129     }
1130   } lookupTy(ACtx);
1131 
1132   // Below are auxiliary classes to handle optional types that we get as a
1133   // result of the lookup.
1134   class GetRestrictTy {
1135     const ASTContext &ACtx;
1136 
1137   public:
1138     GetRestrictTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1139     QualType operator()(QualType Ty) {
1140       return ACtx.getLangOpts().C99 ? ACtx.getRestrictType(Ty) : Ty;
1141     }
1142     Optional<QualType> operator()(Optional<QualType> Ty) {
1143       if (Ty)
1144         return operator()(*Ty);
1145       return None;
1146     }
1147   } getRestrictTy(ACtx);
1148   class GetPointerTy {
1149     const ASTContext &ACtx;
1150 
1151   public:
1152     GetPointerTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1153     QualType operator()(QualType Ty) { return ACtx.getPointerType(Ty); }
1154     Optional<QualType> operator()(Optional<QualType> Ty) {
1155       if (Ty)
1156         return operator()(*Ty);
1157       return None;
1158     }
1159   } getPointerTy(ACtx);
1160   class {
1161   public:
1162     Optional<QualType> operator()(Optional<QualType> Ty) {
1163       return Ty ? Optional<QualType>(Ty->withConst()) : None;
1164     }
1165     QualType operator()(QualType Ty) { return Ty.withConst(); }
1166   } getConstTy;
1167   class GetMaxValue {
1168     BasicValueFactory &BVF;
1169 
1170   public:
1171     GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {}
1172     Optional<RangeInt> operator()(QualType Ty) {
1173       return BVF.getMaxValue(Ty).getLimitedValue();
1174     }
1175     Optional<RangeInt> operator()(Optional<QualType> Ty) {
1176       if (Ty) {
1177         return operator()(*Ty);
1178       }
1179       return None;
1180     }
1181   } getMaxValue(BVF);
1182 
1183   // These types are useful for writing specifications quickly,
1184   // New specifications should probably introduce more types.
1185   // Some types are hard to obtain from the AST, eg. "ssize_t".
1186   // In such cases it should be possible to provide multiple variants
1187   // of function summary for common cases (eg. ssize_t could be int or long
1188   // or long long, so three summary variants would be enough).
1189   // Of course, function variants are also useful for C++ overloads.
1190   const QualType VoidTy = ACtx.VoidTy;
1191   const QualType CharTy = ACtx.CharTy;
1192   const QualType WCharTy = ACtx.WCharTy;
1193   const QualType IntTy = ACtx.IntTy;
1194   const QualType UnsignedIntTy = ACtx.UnsignedIntTy;
1195   const QualType LongTy = ACtx.LongTy;
1196   const QualType SizeTy = ACtx.getSizeType();
1197 
1198   const QualType VoidPtrTy = getPointerTy(VoidTy); // void *
1199   const QualType IntPtrTy = getPointerTy(IntTy);   // int *
1200   const QualType UnsignedIntPtrTy =
1201       getPointerTy(UnsignedIntTy); // unsigned int *
1202   const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy);
1203   const QualType ConstVoidPtrTy =
1204       getPointerTy(getConstTy(VoidTy));            // const void *
1205   const QualType CharPtrTy = getPointerTy(CharTy); // char *
1206   const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy);
1207   const QualType ConstCharPtrTy =
1208       getPointerTy(getConstTy(CharTy)); // const char *
1209   const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy);
1210   const QualType Wchar_tPtrTy = getPointerTy(WCharTy); // wchar_t *
1211   const QualType ConstWchar_tPtrTy =
1212       getPointerTy(getConstTy(WCharTy)); // const wchar_t *
1213   const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy);
1214   const QualType SizePtrTy = getPointerTy(SizeTy);
1215   const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy);
1216 
1217   const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
1218   const RangeInt UnsignedIntMax =
1219       BVF.getMaxValue(UnsignedIntTy).getLimitedValue();
1220   const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
1221   const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue();
1222 
1223   // Set UCharRangeMax to min of int or uchar maximum value.
1224   // The C standard states that the arguments of functions like isalpha must
1225   // be representable as an unsigned char. Their type is 'int', so the max
1226   // value of the argument should be min(UCharMax, IntMax). This just happen
1227   // to be true for commonly used and well tested instruction set
1228   // architectures, but not for others.
1229   const RangeInt UCharRangeMax =
1230       std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
1231 
1232   // The platform dependent value of EOF.
1233   // Try our best to parse this from the Preprocessor, otherwise fallback to -1.
1234   const auto EOFv = [&C]() -> RangeInt {
1235     if (const llvm::Optional<int> OptInt =
1236             tryExpandAsInteger("EOF", C.getPreprocessor()))
1237       return *OptInt;
1238     return -1;
1239   }();
1240 
1241   // Auxiliary class to aid adding summaries to the summary map.
1242   struct AddToFunctionSummaryMap {
1243     const ASTContext &ACtx;
1244     FunctionSummaryMapType &Map;
1245     bool DisplayLoadedSummaries;
1246     AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM,
1247                             bool DisplayLoadedSummaries)
1248         : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) {
1249     }
1250 
1251     // Add a summary to a FunctionDecl found by lookup. The lookup is performed
1252     // by the given Name, and in the global scope. The summary will be attached
1253     // to the found FunctionDecl only if the signatures match.
1254     //
1255     // Returns true if the summary has been added, false otherwise.
1256     bool operator()(StringRef Name, Signature Sign, Summary Sum) {
1257       if (Sign.isInvalid())
1258         return false;
1259       IdentifierInfo &II = ACtx.Idents.get(Name);
1260       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
1261       if (LookupRes.empty())
1262         return false;
1263       for (Decl *D : LookupRes) {
1264         if (auto *FD = dyn_cast<FunctionDecl>(D)) {
1265           if (Sum.matchesAndSet(Sign, FD)) {
1266             auto Res = Map.insert({FD->getCanonicalDecl(), Sum});
1267             assert(Res.second && "Function already has a summary set!");
1268             (void)Res;
1269             if (DisplayLoadedSummaries) {
1270               llvm::errs() << "Loaded summary for: ";
1271               FD->print(llvm::errs());
1272               llvm::errs() << "\n";
1273             }
1274             return true;
1275           }
1276         }
1277       }
1278       return false;
1279     }
1280     // Add the same summary for different names with the Signature explicitly
1281     // given.
1282     void operator()(std::vector<StringRef> Names, Signature Sign, Summary Sum) {
1283       for (StringRef Name : Names)
1284         operator()(Name, Sign, Sum);
1285     }
1286   } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries);
1287 
1288   // Below are helpers functions to create the summaries.
1289   auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind,
1290                               IntRangeVector Ranges) {
1291     return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges);
1292   };
1293   auto BufferSize = [](auto... Args) {
1294     return std::make_shared<BufferSizeConstraint>(Args...);
1295   };
1296   struct {
1297     auto operator()(RangeKind Kind, IntRangeVector Ranges) {
1298       return std::make_shared<RangeConstraint>(Ret, Kind, Ranges);
1299     }
1300     auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) {
1301       return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN);
1302     }
1303   } ReturnValueCondition;
1304   struct {
1305     auto operator()(RangeInt b, RangeInt e) {
1306       return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}};
1307     }
1308     auto operator()(RangeInt b, Optional<RangeInt> e) {
1309       if (e)
1310         return IntRangeVector{std::pair<RangeInt, RangeInt>{b, *e}};
1311       return IntRangeVector{};
1312     }
1313     auto operator()(std::pair<RangeInt, RangeInt> i0,
1314                     std::pair<RangeInt, Optional<RangeInt>> i1) {
1315       if (i1.second)
1316         return IntRangeVector{i0, {i1.first, *(i1.second)}};
1317       return IntRangeVector{i0};
1318     }
1319   } Range;
1320   auto SingleValue = [](RangeInt v) {
1321     return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}};
1322   };
1323   auto LessThanOrEq = BO_LE;
1324   auto NotNull = [&](ArgNo ArgN) {
1325     return std::make_shared<NotNullConstraint>(ArgN);
1326   };
1327 
1328   Optional<QualType> FileTy = lookupTy("FILE");
1329   Optional<QualType> FilePtrTy = getPointerTy(FileTy);
1330   Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy);
1331 
1332   // We are finally ready to define specifications for all supported functions.
1333   //
1334   // Argument ranges should always cover all variants. If return value
1335   // is completely unknown, omit it from the respective range set.
1336   //
1337   // Every item in the list of range sets represents a particular
1338   // execution path the analyzer would need to explore once
1339   // the call is modeled - a new program state is constructed
1340   // for every range set, and each range line in the range set
1341   // corresponds to a specific constraint within this state.
1342 
1343   // The isascii() family of functions.
1344   // The behavior is undefined if the value of the argument is not
1345   // representable as unsigned char or is not equal to EOF. See e.g. C99
1346   // 7.4.1.2 The isalpha function (p: 181-182).
1347   addToFunctionSummaryMap(
1348       "isalnum", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1349       Summary(EvalCallAsPure)
1350           // Boils down to isupper() or islower() or isdigit().
1351           .Case({ArgumentCondition(0U, WithinRange,
1352                                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}),
1353                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1354                 ErrnoIrrelevant, "Assuming the character is alphanumeric")
1355           // The locale-specific range.
1356           // No post-condition. We are completely unaware of
1357           // locale-specific return values.
1358           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1359                 ErrnoIrrelevant)
1360           .Case(
1361               {ArgumentCondition(
1362                    0U, OutOfRange,
1363                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1364                ReturnValueCondition(WithinRange, SingleValue(0))},
1365               ErrnoIrrelevant, "Assuming the character is non-alphanumeric")
1366           .ArgConstraint(ArgumentCondition(
1367               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1368   addToFunctionSummaryMap(
1369       "isalpha", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1370       Summary(EvalCallAsPure)
1371           .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}),
1372                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1373                 ErrnoIrrelevant, "Assuming the character is alphabetical")
1374           // The locale-specific range.
1375           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1376                 ErrnoIrrelevant)
1377           .Case({ArgumentCondition(
1378                      0U, OutOfRange,
1379                      {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1380                  ReturnValueCondition(WithinRange, SingleValue(0))},
1381                 ErrnoIrrelevant, "Assuming the character is non-alphabetical"));
1382   addToFunctionSummaryMap(
1383       "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1384       Summary(EvalCallAsPure)
1385           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1386                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1387                 ErrnoIrrelevant, "Assuming the character is an ASCII character")
1388           .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)),
1389                  ReturnValueCondition(WithinRange, SingleValue(0))},
1390                 ErrnoIrrelevant,
1391                 "Assuming the character is not an ASCII character"));
1392   addToFunctionSummaryMap(
1393       "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1394       Summary(EvalCallAsPure)
1395           .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}),
1396                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1397                 ErrnoIrrelevant, "Assuming the character is a blank character")
1398           .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}),
1399                  ReturnValueCondition(WithinRange, SingleValue(0))},
1400                 ErrnoIrrelevant,
1401                 "Assuming the character is not a blank character"));
1402   addToFunctionSummaryMap(
1403       "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1404       Summary(EvalCallAsPure)
1405           .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}),
1406                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1407                 ErrnoIrrelevant,
1408                 "Assuming the character is a control character")
1409           .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}),
1410                  ReturnValueCondition(WithinRange, SingleValue(0))},
1411                 ErrnoIrrelevant,
1412                 "Assuming the character is not a control character"));
1413   addToFunctionSummaryMap(
1414       "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1415       Summary(EvalCallAsPure)
1416           .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')),
1417                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1418                 ErrnoIrrelevant, "Assuming the character is a digit")
1419           .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')),
1420                  ReturnValueCondition(WithinRange, SingleValue(0))},
1421                 ErrnoIrrelevant, "Assuming the character is not a digit"));
1422   addToFunctionSummaryMap(
1423       "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1424       Summary(EvalCallAsPure)
1425           .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)),
1426                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1427                 ErrnoIrrelevant,
1428                 "Assuming the character has graphical representation")
1429           .Case(
1430               {ArgumentCondition(0U, OutOfRange, Range(33, 126)),
1431                ReturnValueCondition(WithinRange, SingleValue(0))},
1432               ErrnoIrrelevant,
1433               "Assuming the character does not have graphical representation"));
1434   addToFunctionSummaryMap(
1435       "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1436       Summary(EvalCallAsPure)
1437           // Is certainly lowercase.
1438           .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')),
1439                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1440                 ErrnoIrrelevant, "Assuming the character is a lowercase letter")
1441           // Is ascii but not lowercase.
1442           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1443                  ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
1444                  ReturnValueCondition(WithinRange, SingleValue(0))},
1445                 ErrnoIrrelevant,
1446                 "Assuming the character is not a lowercase letter")
1447           // The locale-specific range.
1448           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1449                 ErrnoIrrelevant)
1450           // Is not an unsigned char.
1451           .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)),
1452                  ReturnValueCondition(WithinRange, SingleValue(0))},
1453                 ErrnoIrrelevant));
1454   addToFunctionSummaryMap(
1455       "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1456       Summary(EvalCallAsPure)
1457           .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
1458                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1459                 ErrnoIrrelevant, "Assuming the character is printable")
1460           .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
1461                  ReturnValueCondition(WithinRange, SingleValue(0))},
1462                 ErrnoIrrelevant, "Assuming the character is non-printable"));
1463   addToFunctionSummaryMap(
1464       "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1465       Summary(EvalCallAsPure)
1466           .Case({ArgumentCondition(
1467                      0U, WithinRange,
1468                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1469                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1470                 ErrnoIrrelevant, "Assuming the character is a punctuation mark")
1471           .Case({ArgumentCondition(
1472                      0U, OutOfRange,
1473                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1474                  ReturnValueCondition(WithinRange, SingleValue(0))},
1475                 ErrnoIrrelevant,
1476                 "Assuming the character is not a punctuation mark"));
1477   addToFunctionSummaryMap(
1478       "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1479       Summary(EvalCallAsPure)
1480           // Space, '\f', '\n', '\r', '\t', '\v'.
1481           .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}),
1482                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1483                 ErrnoIrrelevant,
1484                 "Assuming the character is a whitespace character")
1485           // The locale-specific range.
1486           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1487                 ErrnoIrrelevant)
1488           .Case({ArgumentCondition(0U, OutOfRange,
1489                                    {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
1490                  ReturnValueCondition(WithinRange, SingleValue(0))},
1491                 ErrnoIrrelevant,
1492                 "Assuming the character is not a whitespace character"));
1493   addToFunctionSummaryMap(
1494       "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1495       Summary(EvalCallAsPure)
1496           // Is certainly uppercase.
1497           .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
1498                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1499                 ErrnoIrrelevant,
1500                 "Assuming the character is an uppercase letter")
1501           // The locale-specific range.
1502           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1503                 ErrnoIrrelevant)
1504           // Other.
1505           .Case({ArgumentCondition(0U, OutOfRange,
1506                                    {{'A', 'Z'}, {128, UCharRangeMax}}),
1507                  ReturnValueCondition(WithinRange, SingleValue(0))},
1508                 ErrnoIrrelevant,
1509                 "Assuming the character is not an uppercase letter"));
1510   addToFunctionSummaryMap(
1511       "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1512       Summary(EvalCallAsPure)
1513           .Case({ArgumentCondition(0U, WithinRange,
1514                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1515                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1516                 ErrnoIrrelevant,
1517                 "Assuming the character is a hexadecimal digit")
1518           .Case({ArgumentCondition(0U, OutOfRange,
1519                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1520                  ReturnValueCondition(WithinRange, SingleValue(0))},
1521                 ErrnoIrrelevant,
1522                 "Assuming the character is not a hexadecimal digit"));
1523   addToFunctionSummaryMap(
1524       "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1525       Summary(EvalCallAsPure)
1526           .ArgConstraint(ArgumentCondition(
1527               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1528   addToFunctionSummaryMap(
1529       "tolower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1530       Summary(EvalCallAsPure)
1531           .ArgConstraint(ArgumentCondition(
1532               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1533   addToFunctionSummaryMap(
1534       "toascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1535       Summary(EvalCallAsPure)
1536           .ArgConstraint(ArgumentCondition(
1537               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1538 
1539   // The getc() family of functions that returns either a char or an EOF.
1540   addToFunctionSummaryMap(
1541       {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1542       Summary(NoEvalCall)
1543           .Case({ReturnValueCondition(WithinRange,
1544                                       {{EOFv, EOFv}, {0, UCharRangeMax}})},
1545                 ErrnoIrrelevant));
1546   addToFunctionSummaryMap(
1547       "getchar", Signature(ArgTypes{}, RetType{IntTy}),
1548       Summary(NoEvalCall)
1549           .Case({ReturnValueCondition(WithinRange,
1550                                       {{EOFv, EOFv}, {0, UCharRangeMax}})},
1551                 ErrnoIrrelevant));
1552 
1553   // read()-like functions that never return more than buffer size.
1554   auto FreadSummary =
1555       Summary(NoEvalCall)
1556           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1557                  ReturnValueCondition(WithinRange, Range(0, SizeMax))},
1558                 ErrnoIrrelevant)
1559           .ArgConstraint(NotNull(ArgNo(0)))
1560           .ArgConstraint(NotNull(ArgNo(3)))
1561           .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
1562                                     /*BufSizeMultiplier=*/ArgNo(2)));
1563 
1564   // size_t fread(void *restrict ptr, size_t size, size_t nitems,
1565   //              FILE *restrict stream);
1566   addToFunctionSummaryMap(
1567       "fread",
1568       Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
1569                 RetType{SizeTy}),
1570       FreadSummary);
1571   // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
1572   //               FILE *restrict stream);
1573   addToFunctionSummaryMap("fwrite",
1574                           Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy,
1575                                              SizeTy, FilePtrRestrictTy},
1576                                     RetType{SizeTy}),
1577                           FreadSummary);
1578 
1579   Optional<QualType> Ssize_tTy = lookupTy("ssize_t");
1580   Optional<RangeInt> Ssize_tMax = getMaxValue(Ssize_tTy);
1581 
1582   auto ReadSummary =
1583       Summary(NoEvalCall)
1584           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1585                  ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))},
1586                 ErrnoIrrelevant);
1587 
1588   // FIXME these are actually defined by POSIX and not by the C standard, we
1589   // should handle them together with the rest of the POSIX functions.
1590   // ssize_t read(int fildes, void *buf, size_t nbyte);
1591   addToFunctionSummaryMap(
1592       "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1593       ReadSummary);
1594   // ssize_t write(int fildes, const void *buf, size_t nbyte);
1595   addToFunctionSummaryMap(
1596       "write",
1597       Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1598       ReadSummary);
1599 
1600   auto GetLineSummary =
1601       Summary(NoEvalCall)
1602           .Case({ReturnValueCondition(WithinRange,
1603                                       Range({-1, -1}, {1, Ssize_tMax}))},
1604                 ErrnoIrrelevant);
1605 
1606   QualType CharPtrPtrRestrictTy = getRestrictTy(getPointerTy(CharPtrTy));
1607 
1608   // getline()-like functions either fail or read at least the delimiter.
1609   // FIXME these are actually defined by POSIX and not by the C standard, we
1610   // should handle them together with the rest of the POSIX functions.
1611   // ssize_t getline(char **restrict lineptr, size_t *restrict n,
1612   //                 FILE *restrict stream);
1613   addToFunctionSummaryMap(
1614       "getline",
1615       Signature(
1616           ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, FilePtrRestrictTy},
1617           RetType{Ssize_tTy}),
1618       GetLineSummary);
1619   // ssize_t getdelim(char **restrict lineptr, size_t *restrict n,
1620   //                  int delimiter, FILE *restrict stream);
1621   addToFunctionSummaryMap(
1622       "getdelim",
1623       Signature(ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, IntTy,
1624                          FilePtrRestrictTy},
1625                 RetType{Ssize_tTy}),
1626       GetLineSummary);
1627 
1628   {
1629     Summary GetenvSummary =
1630         Summary(NoEvalCall)
1631             .ArgConstraint(NotNull(ArgNo(0)))
1632             .Case({NotNull(Ret)}, ErrnoIrrelevant,
1633                   "Assuming the environment variable exists");
1634     // In untrusted environments the envvar might not exist.
1635     if (!ShouldAssumeControlledEnvironment)
1636       GetenvSummary.Case({NotNull(Ret)->negate()}, ErrnoIrrelevant,
1637                          "Assuming the environment variable does not exist");
1638 
1639     // char *getenv(const char *name);
1640     addToFunctionSummaryMap(
1641         "getenv", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1642         std::move(GetenvSummary));
1643   }
1644 
1645   if (ModelPOSIX) {
1646 
1647     // long a64l(const char *str64);
1648     addToFunctionSummaryMap(
1649         "a64l", Signature(ArgTypes{ConstCharPtrTy}, RetType{LongTy}),
1650         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1651 
1652     // char *l64a(long value);
1653     addToFunctionSummaryMap("l64a",
1654                             Signature(ArgTypes{LongTy}, RetType{CharPtrTy}),
1655                             Summary(NoEvalCall)
1656                                 .ArgConstraint(ArgumentCondition(
1657                                     0, WithinRange, Range(0, LongMax))));
1658 
1659     const auto ReturnsZeroOrMinusOne =
1660         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
1661     const auto ReturnsZero =
1662         ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(0))};
1663     const auto ReturnsMinusOne =
1664         ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(-1))};
1665     const auto ReturnsNonnegative =
1666         ConstraintSet{ReturnValueCondition(WithinRange, Range(0, IntMax))};
1667     const auto ReturnsFileDescriptor =
1668         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
1669     const auto &ReturnsValidFileDescriptor = ReturnsNonnegative;
1670 
1671     // int access(const char *pathname, int amode);
1672     addToFunctionSummaryMap(
1673         "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
1674         Summary(NoEvalCall)
1675             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1676             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1677             .ArgConstraint(NotNull(ArgNo(0))));
1678 
1679     // int faccessat(int dirfd, const char *pathname, int mode, int flags);
1680     addToFunctionSummaryMap(
1681         "faccessat",
1682         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
1683                   RetType{IntTy}),
1684         Summary(NoEvalCall)
1685             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1686             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1687             .ArgConstraint(NotNull(ArgNo(1))));
1688 
1689     // int dup(int fildes);
1690     addToFunctionSummaryMap(
1691         "dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1692         Summary(NoEvalCall)
1693             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1694             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1695             .ArgConstraint(
1696                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1697 
1698     // int dup2(int fildes1, int filedes2);
1699     addToFunctionSummaryMap(
1700         "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
1701         Summary(NoEvalCall)
1702             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1703             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1704             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1705             .ArgConstraint(
1706                 ArgumentCondition(1, WithinRange, Range(0, IntMax))));
1707 
1708     // int fdatasync(int fildes);
1709     addToFunctionSummaryMap("fdatasync",
1710                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
1711                             Summary(NoEvalCall)
1712                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1713                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1714                                 .ArgConstraint(ArgumentCondition(
1715                                     0, WithinRange, Range(0, IntMax))));
1716 
1717     // int fnmatch(const char *pattern, const char *string, int flags);
1718     addToFunctionSummaryMap(
1719         "fnmatch",
1720         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy},
1721                   RetType{IntTy}),
1722         Summary(NoEvalCall)
1723             .ArgConstraint(NotNull(ArgNo(0)))
1724             .ArgConstraint(NotNull(ArgNo(1))));
1725 
1726     // int fsync(int fildes);
1727     addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1728                             Summary(NoEvalCall)
1729                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1730                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1731                                 .ArgConstraint(ArgumentCondition(
1732                                     0, WithinRange, Range(0, IntMax))));
1733 
1734     Optional<QualType> Off_tTy = lookupTy("off_t");
1735 
1736     // int truncate(const char *path, off_t length);
1737     addToFunctionSummaryMap(
1738         "truncate",
1739         Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
1740         Summary(NoEvalCall)
1741             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1742             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1743             .ArgConstraint(NotNull(ArgNo(0))));
1744 
1745     // int symlink(const char *oldpath, const char *newpath);
1746     addToFunctionSummaryMap(
1747         "symlink",
1748         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
1749         Summary(NoEvalCall)
1750             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1751             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1752             .ArgConstraint(NotNull(ArgNo(0)))
1753             .ArgConstraint(NotNull(ArgNo(1))));
1754 
1755     // int symlinkat(const char *oldpath, int newdirfd, const char *newpath);
1756     addToFunctionSummaryMap(
1757         "symlinkat",
1758         Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
1759                   RetType{IntTy}),
1760         Summary(NoEvalCall)
1761             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1762             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1763             .ArgConstraint(NotNull(ArgNo(0)))
1764             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
1765             .ArgConstraint(NotNull(ArgNo(2))));
1766 
1767     // int lockf(int fd, int cmd, off_t len);
1768     addToFunctionSummaryMap(
1769         "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}),
1770         Summary(NoEvalCall)
1771             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1772             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1773             .ArgConstraint(
1774                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1775 
1776     Optional<QualType> Mode_tTy = lookupTy("mode_t");
1777 
1778     // int creat(const char *pathname, mode_t mode);
1779     addToFunctionSummaryMap(
1780         "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1781         Summary(NoEvalCall)
1782             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1783             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1784             .ArgConstraint(NotNull(ArgNo(0))));
1785 
1786     // unsigned int sleep(unsigned int seconds);
1787     addToFunctionSummaryMap(
1788         "sleep", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
1789         Summary(NoEvalCall)
1790             .ArgConstraint(
1791                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1792 
1793     Optional<QualType> DirTy = lookupTy("DIR");
1794     Optional<QualType> DirPtrTy = getPointerTy(DirTy);
1795 
1796     // int dirfd(DIR *dirp);
1797     addToFunctionSummaryMap(
1798         "dirfd", Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1799         Summary(NoEvalCall)
1800             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1801             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1802             .ArgConstraint(NotNull(ArgNo(0))));
1803 
1804     // unsigned int alarm(unsigned int seconds);
1805     addToFunctionSummaryMap(
1806         "alarm", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
1807         Summary(NoEvalCall)
1808             .ArgConstraint(
1809                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1810 
1811     // int closedir(DIR *dir);
1812     addToFunctionSummaryMap("closedir",
1813                             Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1814                             Summary(NoEvalCall)
1815                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1816                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1817                                 .ArgConstraint(NotNull(ArgNo(0))));
1818 
1819     // char *strdup(const char *s);
1820     addToFunctionSummaryMap(
1821         "strdup", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1822         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1823 
1824     // char *strndup(const char *s, size_t n);
1825     addToFunctionSummaryMap(
1826         "strndup",
1827         Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}),
1828         Summary(NoEvalCall)
1829             .ArgConstraint(NotNull(ArgNo(0)))
1830             .ArgConstraint(
1831                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1832 
1833     // wchar_t *wcsdup(const wchar_t *s);
1834     addToFunctionSummaryMap(
1835         "wcsdup", Signature(ArgTypes{ConstWchar_tPtrTy}, RetType{Wchar_tPtrTy}),
1836         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1837 
1838     // int mkstemp(char *template);
1839     addToFunctionSummaryMap(
1840         "mkstemp", Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
1841         Summary(NoEvalCall)
1842             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1843             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1844             .ArgConstraint(NotNull(ArgNo(0))));
1845 
1846     // char *mkdtemp(char *template);
1847     // FIXME: Improve for errno modeling.
1848     addToFunctionSummaryMap(
1849         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
1850         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1851 
1852     // char *getcwd(char *buf, size_t size);
1853     // FIXME: Improve for errno modeling.
1854     addToFunctionSummaryMap(
1855         "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
1856         Summary(NoEvalCall)
1857             .ArgConstraint(
1858                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1859 
1860     // int mkdir(const char *pathname, mode_t mode);
1861     addToFunctionSummaryMap(
1862         "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1863         Summary(NoEvalCall)
1864             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1865             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1866             .ArgConstraint(NotNull(ArgNo(0))));
1867 
1868     // int mkdirat(int dirfd, const char *pathname, mode_t mode);
1869     addToFunctionSummaryMap(
1870         "mkdirat",
1871         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1872         Summary(NoEvalCall)
1873             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1874             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1875             .ArgConstraint(NotNull(ArgNo(1))));
1876 
1877     Optional<QualType> Dev_tTy = lookupTy("dev_t");
1878 
1879     // int mknod(const char *pathname, mode_t mode, dev_t dev);
1880     addToFunctionSummaryMap(
1881         "mknod",
1882         Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}),
1883         Summary(NoEvalCall)
1884             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1885             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1886             .ArgConstraint(NotNull(ArgNo(0))));
1887 
1888     // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
1889     addToFunctionSummaryMap(
1890         "mknodat",
1891         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy},
1892                   RetType{IntTy}),
1893         Summary(NoEvalCall)
1894             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1895             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1896             .ArgConstraint(NotNull(ArgNo(1))));
1897 
1898     // int chmod(const char *path, mode_t mode);
1899     addToFunctionSummaryMap(
1900         "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1901         Summary(NoEvalCall)
1902             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1903             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1904             .ArgConstraint(NotNull(ArgNo(0))));
1905 
1906     // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
1907     addToFunctionSummaryMap(
1908         "fchmodat",
1909         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy},
1910                   RetType{IntTy}),
1911         Summary(NoEvalCall)
1912             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1913             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1914             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1915             .ArgConstraint(NotNull(ArgNo(1))));
1916 
1917     // int fchmod(int fildes, mode_t mode);
1918     addToFunctionSummaryMap(
1919         "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}),
1920         Summary(NoEvalCall)
1921             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1922             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1923             .ArgConstraint(
1924                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1925 
1926     Optional<QualType> Uid_tTy = lookupTy("uid_t");
1927     Optional<QualType> Gid_tTy = lookupTy("gid_t");
1928 
1929     // int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group,
1930     //              int flags);
1931     addToFunctionSummaryMap(
1932         "fchownat",
1933         Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy},
1934                   RetType{IntTy}),
1935         Summary(NoEvalCall)
1936             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1937             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1938             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1939             .ArgConstraint(NotNull(ArgNo(1))));
1940 
1941     // int chown(const char *path, uid_t owner, gid_t group);
1942     addToFunctionSummaryMap(
1943         "chown",
1944         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1945         Summary(NoEvalCall)
1946             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1947             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1948             .ArgConstraint(NotNull(ArgNo(0))));
1949 
1950     // int lchown(const char *path, uid_t owner, gid_t group);
1951     addToFunctionSummaryMap(
1952         "lchown",
1953         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1954         Summary(NoEvalCall)
1955             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1956             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1957             .ArgConstraint(NotNull(ArgNo(0))));
1958 
1959     // int fchown(int fildes, uid_t owner, gid_t group);
1960     addToFunctionSummaryMap(
1961         "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1962         Summary(NoEvalCall)
1963             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1964             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1965             .ArgConstraint(
1966                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1967 
1968     // int rmdir(const char *pathname);
1969     addToFunctionSummaryMap("rmdir",
1970                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1971                             Summary(NoEvalCall)
1972                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1973                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1974                                 .ArgConstraint(NotNull(ArgNo(0))));
1975 
1976     // int chdir(const char *path);
1977     addToFunctionSummaryMap("chdir",
1978                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1979                             Summary(NoEvalCall)
1980                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1981                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1982                                 .ArgConstraint(NotNull(ArgNo(0))));
1983 
1984     // int link(const char *oldpath, const char *newpath);
1985     addToFunctionSummaryMap(
1986         "link",
1987         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
1988         Summary(NoEvalCall)
1989             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1990             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1991             .ArgConstraint(NotNull(ArgNo(0)))
1992             .ArgConstraint(NotNull(ArgNo(1))));
1993 
1994     // int linkat(int fd1, const char *path1, int fd2, const char *path2,
1995     //            int flag);
1996     addToFunctionSummaryMap(
1997         "linkat",
1998         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy},
1999                   RetType{IntTy}),
2000         Summary(NoEvalCall)
2001             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2002             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2003             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2004             .ArgConstraint(NotNull(ArgNo(1)))
2005             .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
2006             .ArgConstraint(NotNull(ArgNo(3))));
2007 
2008     // int unlink(const char *pathname);
2009     addToFunctionSummaryMap("unlink",
2010                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
2011                             Summary(NoEvalCall)
2012                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2013                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2014                                 .ArgConstraint(NotNull(ArgNo(0))));
2015 
2016     // int unlinkat(int fd, const char *path, int flag);
2017     addToFunctionSummaryMap(
2018         "unlinkat",
2019         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}),
2020         Summary(NoEvalCall)
2021             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2022             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2023             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2024             .ArgConstraint(NotNull(ArgNo(1))));
2025 
2026     Optional<QualType> StructStatTy = lookupTy("stat");
2027     Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy);
2028     Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy);
2029 
2030     // int fstat(int fd, struct stat *statbuf);
2031     addToFunctionSummaryMap(
2032         "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}),
2033         Summary(NoEvalCall)
2034             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2035             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2036             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2037             .ArgConstraint(NotNull(ArgNo(1))));
2038 
2039     // int stat(const char *restrict path, struct stat *restrict buf);
2040     addToFunctionSummaryMap(
2041         "stat",
2042         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
2043                   RetType{IntTy}),
2044         Summary(NoEvalCall)
2045             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2046             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2047             .ArgConstraint(NotNull(ArgNo(0)))
2048             .ArgConstraint(NotNull(ArgNo(1))));
2049 
2050     // int lstat(const char *restrict path, struct stat *restrict buf);
2051     addToFunctionSummaryMap(
2052         "lstat",
2053         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
2054                   RetType{IntTy}),
2055         Summary(NoEvalCall)
2056             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2057             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2058             .ArgConstraint(NotNull(ArgNo(0)))
2059             .ArgConstraint(NotNull(ArgNo(1))));
2060 
2061     // int fstatat(int fd, const char *restrict path,
2062     //             struct stat *restrict buf, int flag);
2063     addToFunctionSummaryMap(
2064         "fstatat",
2065         Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy,
2066                            StructStatPtrRestrictTy, IntTy},
2067                   RetType{IntTy}),
2068         Summary(NoEvalCall)
2069             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2070             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2071             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2072             .ArgConstraint(NotNull(ArgNo(1)))
2073             .ArgConstraint(NotNull(ArgNo(2))));
2074 
2075     // DIR *opendir(const char *name);
2076     // FIXME: Improve for errno modeling.
2077     addToFunctionSummaryMap(
2078         "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
2079         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2080 
2081     // DIR *fdopendir(int fd);
2082     // FIXME: Improve for errno modeling.
2083     addToFunctionSummaryMap("fdopendir",
2084                             Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
2085                             Summary(NoEvalCall)
2086                                 .ArgConstraint(ArgumentCondition(
2087                                     0, WithinRange, Range(0, IntMax))));
2088 
2089     // int isatty(int fildes);
2090     addToFunctionSummaryMap(
2091         "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2092         Summary(NoEvalCall)
2093             .Case({ReturnValueCondition(WithinRange, Range(0, 1))},
2094                   ErrnoIrrelevant)
2095             .ArgConstraint(
2096                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2097 
2098     // FILE *popen(const char *command, const char *type);
2099     // FIXME: Improve for errno modeling.
2100     addToFunctionSummaryMap(
2101         "popen",
2102         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}),
2103         Summary(NoEvalCall)
2104             .ArgConstraint(NotNull(ArgNo(0)))
2105             .ArgConstraint(NotNull(ArgNo(1))));
2106 
2107     // int pclose(FILE *stream);
2108     // FIXME: Improve for errno modeling.
2109     addToFunctionSummaryMap(
2110         "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
2111         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2112 
2113     // int close(int fildes);
2114     addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2115                             Summary(NoEvalCall)
2116                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2117                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2118                                 .ArgConstraint(ArgumentCondition(
2119                                     0, WithinRange, Range(-1, IntMax))));
2120 
2121     // long fpathconf(int fildes, int name);
2122     addToFunctionSummaryMap("fpathconf",
2123                             Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}),
2124                             Summary(NoEvalCall)
2125                                 .ArgConstraint(ArgumentCondition(
2126                                     0, WithinRange, Range(0, IntMax))));
2127 
2128     // long pathconf(const char *path, int name);
2129     addToFunctionSummaryMap(
2130         "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}),
2131         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2132 
2133     // FILE *fdopen(int fd, const char *mode);
2134     // FIXME: Improve for errno modeling.
2135     addToFunctionSummaryMap(
2136         "fdopen",
2137         Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}),
2138         Summary(NoEvalCall)
2139             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2140             .ArgConstraint(NotNull(ArgNo(1))));
2141 
2142     // void rewinddir(DIR *dir);
2143     addToFunctionSummaryMap(
2144         "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}),
2145         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2146 
2147     // void seekdir(DIR *dirp, long loc);
2148     addToFunctionSummaryMap(
2149         "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}),
2150         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2151 
2152     // int rand_r(unsigned int *seedp);
2153     addToFunctionSummaryMap(
2154         "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}),
2155         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2156 
2157     // int fileno(FILE *stream);
2158     addToFunctionSummaryMap(
2159         "fileno", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
2160         Summary(NoEvalCall)
2161             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
2162             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2163             .ArgConstraint(NotNull(ArgNo(0))));
2164 
2165     // int fseeko(FILE *stream, off_t offset, int whence);
2166     addToFunctionSummaryMap(
2167         "fseeko",
2168         Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
2169         Summary(NoEvalCall)
2170             .Case(ReturnsZeroOrMinusOne, ErrnoIrrelevant)
2171             .ArgConstraint(NotNull(ArgNo(0))));
2172 
2173     // off_t ftello(FILE *stream);
2174     addToFunctionSummaryMap(
2175         "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
2176         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2177 
2178     // void *mmap(void *addr, size_t length, int prot, int flags, int fd,
2179     // off_t offset);
2180     // FIXME: Improve for errno modeling.
2181     addToFunctionSummaryMap(
2182         "mmap",
2183         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
2184                   RetType{VoidPtrTy}),
2185         Summary(NoEvalCall)
2186             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
2187             .ArgConstraint(
2188                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
2189 
2190     Optional<QualType> Off64_tTy = lookupTy("off64_t");
2191     // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
2192     // off64_t offset);
2193     // FIXME: Improve for errno modeling.
2194     addToFunctionSummaryMap(
2195         "mmap64",
2196         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
2197                   RetType{VoidPtrTy}),
2198         Summary(NoEvalCall)
2199             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
2200             .ArgConstraint(
2201                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
2202 
2203     // int pipe(int fildes[2]);
2204     addToFunctionSummaryMap("pipe",
2205                             Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2206                             Summary(NoEvalCall)
2207                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2208                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2209                                 .ArgConstraint(NotNull(ArgNo(0))));
2210 
2211     // off_t lseek(int fildes, off_t offset, int whence);
2212     // In the first case we can not tell for sure if it failed or not.
2213     // A return value different from of the expected offset (that is unknown
2214     // here) may indicate failure. For this reason we do not enforce the errno
2215     // check (can cause false positive).
2216     addToFunctionSummaryMap(
2217         "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}),
2218         Summary(NoEvalCall)
2219             .Case(ReturnsNonnegative, ErrnoIrrelevant)
2220             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2221             .ArgConstraint(
2222                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2223 
2224     // ssize_t readlink(const char *restrict path, char *restrict buf,
2225     //                  size_t bufsize);
2226     addToFunctionSummaryMap(
2227         "readlink",
2228         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
2229                   RetType{Ssize_tTy}),
2230         Summary(NoEvalCall)
2231             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2232                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2233                   ErrnoMustNotBeChecked)
2234             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2235             .ArgConstraint(NotNull(ArgNo(0)))
2236             .ArgConstraint(NotNull(ArgNo(1)))
2237             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2238                                       /*BufSize=*/ArgNo(2)))
2239             .ArgConstraint(
2240                 ArgumentCondition(2, WithinRange, Range(0, SizeMax))));
2241 
2242     // ssize_t readlinkat(int fd, const char *restrict path,
2243     //                    char *restrict buf, size_t bufsize);
2244     addToFunctionSummaryMap(
2245         "readlinkat",
2246         Signature(
2247             ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
2248             RetType{Ssize_tTy}),
2249         Summary(NoEvalCall)
2250             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
2251                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2252                   ErrnoMustNotBeChecked)
2253             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2254             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2255             .ArgConstraint(NotNull(ArgNo(1)))
2256             .ArgConstraint(NotNull(ArgNo(2)))
2257             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
2258                                       /*BufSize=*/ArgNo(3)))
2259             .ArgConstraint(
2260                 ArgumentCondition(3, WithinRange, Range(0, SizeMax))));
2261 
2262     // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char
2263     // *newpath);
2264     addToFunctionSummaryMap(
2265         "renameat",
2266         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy},
2267                   RetType{IntTy}),
2268         Summary(NoEvalCall)
2269             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2270             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2271             .ArgConstraint(NotNull(ArgNo(1)))
2272             .ArgConstraint(NotNull(ArgNo(3))));
2273 
2274     // char *realpath(const char *restrict file_name,
2275     //                char *restrict resolved_name);
2276     // FIXME: Improve for errno modeling.
2277     addToFunctionSummaryMap(
2278         "realpath",
2279         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
2280                   RetType{CharPtrTy}),
2281         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2282 
2283     QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy));
2284 
2285     // int execv(const char *path, char *const argv[]);
2286     addToFunctionSummaryMap(
2287         "execv",
2288         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2289         Summary(NoEvalCall)
2290             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
2291                   ErrnoIrrelevant)
2292             .ArgConstraint(NotNull(ArgNo(0))));
2293 
2294     // int execvp(const char *file, char *const argv[]);
2295     addToFunctionSummaryMap(
2296         "execvp",
2297         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2298         Summary(NoEvalCall)
2299             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
2300                   ErrnoIrrelevant)
2301             .ArgConstraint(NotNull(ArgNo(0))));
2302 
2303     // int getopt(int argc, char * const argv[], const char *optstring);
2304     addToFunctionSummaryMap(
2305         "getopt",
2306         Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
2307                   RetType{IntTy}),
2308         Summary(NoEvalCall)
2309             .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))},
2310                   ErrnoIrrelevant)
2311             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2312             .ArgConstraint(NotNull(ArgNo(1)))
2313             .ArgConstraint(NotNull(ArgNo(2))));
2314 
2315     Optional<QualType> StructSockaddrTy = lookupTy("sockaddr");
2316     Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy);
2317     Optional<QualType> ConstStructSockaddrPtrTy =
2318         getPointerTy(getConstTy(StructSockaddrTy));
2319     Optional<QualType> StructSockaddrPtrRestrictTy =
2320         getRestrictTy(StructSockaddrPtrTy);
2321     Optional<QualType> ConstStructSockaddrPtrRestrictTy =
2322         getRestrictTy(ConstStructSockaddrPtrTy);
2323     Optional<QualType> Socklen_tTy = lookupTy("socklen_t");
2324     Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy);
2325     Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
2326     Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy);
2327 
2328     // In 'socket.h' of some libc implementations with C99, sockaddr parameter
2329     // is a transparent union of the underlying sockaddr_ family of pointers
2330     // instead of being a pointer to struct sockaddr. In these cases, the
2331     // standardized signature will not match, thus we try to match with another
2332     // signature that has the joker Irrelevant type. We also remove those
2333     // constraints which require pointer types for the sockaddr param.
2334     auto Accept =
2335         Summary(NoEvalCall)
2336             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
2337             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2338             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
2339     if (!addToFunctionSummaryMap(
2340             "accept",
2341             // int accept(int socket, struct sockaddr *restrict address,
2342             //            socklen_t *restrict address_len);
2343             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2344                                Socklen_tPtrRestrictTy},
2345                       RetType{IntTy}),
2346             Accept))
2347       addToFunctionSummaryMap(
2348           "accept",
2349           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2350                     RetType{IntTy}),
2351           Accept);
2352 
2353     // int bind(int socket, const struct sockaddr *address, socklen_t
2354     //          address_len);
2355     if (!addToFunctionSummaryMap(
2356             "bind",
2357             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
2358                       RetType{IntTy}),
2359             Summary(NoEvalCall)
2360                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2361                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2362                 .ArgConstraint(
2363                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2364                 .ArgConstraint(NotNull(ArgNo(1)))
2365                 .ArgConstraint(
2366                     BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))
2367                 .ArgConstraint(
2368                     ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))))
2369       // Do not add constraints on sockaddr.
2370       addToFunctionSummaryMap(
2371           "bind",
2372           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
2373           Summary(NoEvalCall)
2374               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2375               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2376               .ArgConstraint(
2377                   ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2378               .ArgConstraint(
2379                   ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))));
2380 
2381     // int getpeername(int socket, struct sockaddr *restrict address,
2382     //                 socklen_t *restrict address_len);
2383     if (!addToFunctionSummaryMap(
2384             "getpeername",
2385             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2386                                Socklen_tPtrRestrictTy},
2387                       RetType{IntTy}),
2388             Summary(NoEvalCall)
2389                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2390                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2391                 .ArgConstraint(
2392                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2393                 .ArgConstraint(NotNull(ArgNo(1)))
2394                 .ArgConstraint(NotNull(ArgNo(2)))))
2395       addToFunctionSummaryMap(
2396           "getpeername",
2397           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2398                     RetType{IntTy}),
2399           Summary(NoEvalCall)
2400               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2401               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2402               .ArgConstraint(
2403                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2404 
2405     // int getsockname(int socket, struct sockaddr *restrict address,
2406     //                 socklen_t *restrict address_len);
2407     if (!addToFunctionSummaryMap(
2408             "getsockname",
2409             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2410                                Socklen_tPtrRestrictTy},
2411                       RetType{IntTy}),
2412             Summary(NoEvalCall)
2413                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2414                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2415                 .ArgConstraint(
2416                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2417                 .ArgConstraint(NotNull(ArgNo(1)))
2418                 .ArgConstraint(NotNull(ArgNo(2)))))
2419       addToFunctionSummaryMap(
2420           "getsockname",
2421           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2422                     RetType{IntTy}),
2423           Summary(NoEvalCall)
2424               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2425               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2426               .ArgConstraint(
2427                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2428 
2429     // int connect(int socket, const struct sockaddr *address, socklen_t
2430     //             address_len);
2431     if (!addToFunctionSummaryMap(
2432             "connect",
2433             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
2434                       RetType{IntTy}),
2435             Summary(NoEvalCall)
2436                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2437                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2438                 .ArgConstraint(
2439                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2440                 .ArgConstraint(NotNull(ArgNo(1)))))
2441       addToFunctionSummaryMap(
2442           "connect",
2443           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
2444           Summary(NoEvalCall)
2445               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2446               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2447               .ArgConstraint(
2448                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2449 
2450     auto Recvfrom =
2451         Summary(NoEvalCall)
2452             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2453                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2454                   ErrnoMustNotBeChecked)
2455             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2456             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2457             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2458                                       /*BufSize=*/ArgNo(2)));
2459     if (!addToFunctionSummaryMap(
2460             "recvfrom",
2461             // ssize_t recvfrom(int socket, void *restrict buffer,
2462             //                  size_t length,
2463             //                  int flags, struct sockaddr *restrict address,
2464             //                  socklen_t *restrict address_len);
2465             Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2466                                StructSockaddrPtrRestrictTy,
2467                                Socklen_tPtrRestrictTy},
2468                       RetType{Ssize_tTy}),
2469             Recvfrom))
2470       addToFunctionSummaryMap(
2471           "recvfrom",
2472           Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2473                              Irrelevant, Socklen_tPtrRestrictTy},
2474                     RetType{Ssize_tTy}),
2475           Recvfrom);
2476 
2477     auto Sendto =
2478         Summary(NoEvalCall)
2479             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2480                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2481                   ErrnoMustNotBeChecked)
2482             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2483             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2484             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2485                                       /*BufSize=*/ArgNo(2)));
2486     if (!addToFunctionSummaryMap(
2487             "sendto",
2488             // ssize_t sendto(int socket, const void *message, size_t length,
2489             //                int flags, const struct sockaddr *dest_addr,
2490             //                socklen_t dest_len);
2491             Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy,
2492                                ConstStructSockaddrPtrTy, Socklen_tTy},
2493                       RetType{Ssize_tTy}),
2494             Sendto))
2495       addToFunctionSummaryMap(
2496           "sendto",
2497           Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant,
2498                              Socklen_tTy},
2499                     RetType{Ssize_tTy}),
2500           Sendto);
2501 
2502     // int listen(int sockfd, int backlog);
2503     addToFunctionSummaryMap("listen",
2504                             Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
2505                             Summary(NoEvalCall)
2506                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2507                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2508                                 .ArgConstraint(ArgumentCondition(
2509                                     0, WithinRange, Range(0, IntMax))));
2510 
2511     // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
2512     addToFunctionSummaryMap(
2513         "recv",
2514         Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy},
2515                   RetType{Ssize_tTy}),
2516         Summary(NoEvalCall)
2517             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2518                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2519                   ErrnoMustNotBeChecked)
2520             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2521             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2522             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2523                                       /*BufSize=*/ArgNo(2))));
2524 
2525     Optional<QualType> StructMsghdrTy = lookupTy("msghdr");
2526     Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy);
2527     Optional<QualType> ConstStructMsghdrPtrTy =
2528         getPointerTy(getConstTy(StructMsghdrTy));
2529 
2530     // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
2531     addToFunctionSummaryMap(
2532         "recvmsg",
2533         Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
2534                   RetType{Ssize_tTy}),
2535         Summary(NoEvalCall)
2536             .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2537                   ErrnoMustNotBeChecked)
2538             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2539             .ArgConstraint(
2540                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2541 
2542     // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
2543     addToFunctionSummaryMap(
2544         "sendmsg",
2545         Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
2546                   RetType{Ssize_tTy}),
2547         Summary(NoEvalCall)
2548             .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2549                   ErrnoMustNotBeChecked)
2550             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2551             .ArgConstraint(
2552                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2553 
2554     // int setsockopt(int socket, int level, int option_name,
2555     //                const void *option_value, socklen_t option_len);
2556     addToFunctionSummaryMap(
2557         "setsockopt",
2558         Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
2559                   RetType{IntTy}),
2560         Summary(NoEvalCall)
2561             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2562             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2563             .ArgConstraint(NotNull(ArgNo(3)))
2564             .ArgConstraint(
2565                 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
2566             .ArgConstraint(
2567                 ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax))));
2568 
2569     // int getsockopt(int socket, int level, int option_name,
2570     //                void *restrict option_value,
2571     //                socklen_t *restrict option_len);
2572     addToFunctionSummaryMap(
2573         "getsockopt",
2574         Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy,
2575                            Socklen_tPtrRestrictTy},
2576                   RetType{IntTy}),
2577         Summary(NoEvalCall)
2578             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2579             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2580             .ArgConstraint(NotNull(ArgNo(3)))
2581             .ArgConstraint(NotNull(ArgNo(4))));
2582 
2583     // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
2584     addToFunctionSummaryMap(
2585         "send",
2586         Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy},
2587                   RetType{Ssize_tTy}),
2588         Summary(NoEvalCall)
2589             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2590                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2591                   ErrnoMustNotBeChecked)
2592             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2593             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2594             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2595                                       /*BufSize=*/ArgNo(2))));
2596 
2597     // int socketpair(int domain, int type, int protocol, int sv[2]);
2598     addToFunctionSummaryMap(
2599         "socketpair",
2600         Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}),
2601         Summary(NoEvalCall)
2602             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2603             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2604             .ArgConstraint(NotNull(ArgNo(3))));
2605 
2606     // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
2607     //                 char *restrict node, socklen_t nodelen,
2608     //                 char *restrict service,
2609     //                 socklen_t servicelen, int flags);
2610     //
2611     // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr
2612     // parameter is never handled as a transparent union in netdb.h
2613     addToFunctionSummaryMap(
2614         "getnameinfo",
2615         Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy,
2616                            CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy,
2617                            Socklen_tTy, IntTy},
2618                   RetType{IntTy}),
2619         Summary(NoEvalCall)
2620             .ArgConstraint(
2621                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
2622             .ArgConstraint(
2623                 ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax)))
2624             .ArgConstraint(
2625                 BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3)))
2626             .ArgConstraint(
2627                 ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax)))
2628             .ArgConstraint(
2629                 BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
2630             .ArgConstraint(
2631                 ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax))));
2632 
2633     Optional<QualType> StructUtimbufTy = lookupTy("utimbuf");
2634     Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy);
2635 
2636     // int utime(const char *filename, struct utimbuf *buf);
2637     addToFunctionSummaryMap(
2638         "utime",
2639         Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}),
2640         Summary(NoEvalCall)
2641             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2642             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2643             .ArgConstraint(NotNull(ArgNo(0))));
2644 
2645     Optional<QualType> StructTimespecTy = lookupTy("timespec");
2646     Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy);
2647     Optional<QualType> ConstStructTimespecPtrTy =
2648         getPointerTy(getConstTy(StructTimespecTy));
2649 
2650     // int futimens(int fd, const struct timespec times[2]);
2651     addToFunctionSummaryMap(
2652         "futimens",
2653         Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}),
2654         Summary(NoEvalCall)
2655             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2656             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2657             .ArgConstraint(
2658                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2659 
2660     // int utimensat(int dirfd, const char *pathname,
2661     //               const struct timespec times[2], int flags);
2662     addToFunctionSummaryMap("utimensat",
2663                             Signature(ArgTypes{IntTy, ConstCharPtrTy,
2664                                                ConstStructTimespecPtrTy, IntTy},
2665                                       RetType{IntTy}),
2666                             Summary(NoEvalCall)
2667                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2668                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2669                                 .ArgConstraint(NotNull(ArgNo(1))));
2670 
2671     Optional<QualType> StructTimevalTy = lookupTy("timeval");
2672     Optional<QualType> ConstStructTimevalPtrTy =
2673         getPointerTy(getConstTy(StructTimevalTy));
2674 
2675     // int utimes(const char *filename, const struct timeval times[2]);
2676     addToFunctionSummaryMap(
2677         "utimes",
2678         Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
2679                   RetType{IntTy}),
2680         Summary(NoEvalCall)
2681             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2682             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2683             .ArgConstraint(NotNull(ArgNo(0))));
2684 
2685     // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
2686     addToFunctionSummaryMap(
2687         "nanosleep",
2688         Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
2689                   RetType{IntTy}),
2690         Summary(NoEvalCall)
2691             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2692             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2693             .ArgConstraint(NotNull(ArgNo(0))));
2694 
2695     Optional<QualType> Time_tTy = lookupTy("time_t");
2696     Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy));
2697     Optional<QualType> ConstTime_tPtrRestrictTy =
2698         getRestrictTy(ConstTime_tPtrTy);
2699 
2700     Optional<QualType> StructTmTy = lookupTy("tm");
2701     Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy);
2702     Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy);
2703     Optional<QualType> ConstStructTmPtrTy =
2704         getPointerTy(getConstTy(StructTmTy));
2705     Optional<QualType> ConstStructTmPtrRestrictTy =
2706         getRestrictTy(ConstStructTmPtrTy);
2707 
2708     // struct tm * localtime(const time_t *tp);
2709     addToFunctionSummaryMap(
2710         "localtime",
2711         Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
2712         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2713 
2714     // struct tm *localtime_r(const time_t *restrict timer,
2715     //                        struct tm *restrict result);
2716     addToFunctionSummaryMap(
2717         "localtime_r",
2718         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2719                   RetType{StructTmPtrTy}),
2720         Summary(NoEvalCall)
2721             .ArgConstraint(NotNull(ArgNo(0)))
2722             .ArgConstraint(NotNull(ArgNo(1))));
2723 
2724     // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
2725     addToFunctionSummaryMap(
2726         "asctime_r",
2727         Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
2728                   RetType{CharPtrTy}),
2729         Summary(NoEvalCall)
2730             .ArgConstraint(NotNull(ArgNo(0)))
2731             .ArgConstraint(NotNull(ArgNo(1)))
2732             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2733                                       /*MinBufSize=*/BVF.getValue(26, IntTy))));
2734 
2735     // char *ctime_r(const time_t *timep, char *buf);
2736     addToFunctionSummaryMap(
2737         "ctime_r",
2738         Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}),
2739         Summary(NoEvalCall)
2740             .ArgConstraint(NotNull(ArgNo(0)))
2741             .ArgConstraint(NotNull(ArgNo(1)))
2742             .ArgConstraint(BufferSize(
2743                 /*Buffer=*/ArgNo(1),
2744                 /*MinBufSize=*/BVF.getValue(26, IntTy))));
2745 
2746     // struct tm *gmtime_r(const time_t *restrict timer,
2747     //                     struct tm *restrict result);
2748     addToFunctionSummaryMap(
2749         "gmtime_r",
2750         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2751                   RetType{StructTmPtrTy}),
2752         Summary(NoEvalCall)
2753             .ArgConstraint(NotNull(ArgNo(0)))
2754             .ArgConstraint(NotNull(ArgNo(1))));
2755 
2756     // struct tm * gmtime(const time_t *tp);
2757     addToFunctionSummaryMap(
2758         "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
2759         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2760 
2761     Optional<QualType> Clockid_tTy = lookupTy("clockid_t");
2762 
2763     // int clock_gettime(clockid_t clock_id, struct timespec *tp);
2764     addToFunctionSummaryMap(
2765         "clock_gettime",
2766         Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}),
2767         Summary(NoEvalCall)
2768             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2769             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2770             .ArgConstraint(NotNull(ArgNo(1))));
2771 
2772     Optional<QualType> StructItimervalTy = lookupTy("itimerval");
2773     Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy);
2774 
2775     // int getitimer(int which, struct itimerval *curr_value);
2776     addToFunctionSummaryMap(
2777         "getitimer",
2778         Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}),
2779         Summary(NoEvalCall)
2780             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2781             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2782             .ArgConstraint(NotNull(ArgNo(1))));
2783 
2784     Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
2785     Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy);
2786     Optional<QualType> Pthread_tTy = lookupTy("pthread_t");
2787     Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy);
2788     Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy);
2789     Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t");
2790     Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy);
2791     Optional<QualType> Pthread_mutex_tPtrRestrictTy =
2792         getRestrictTy(Pthread_mutex_tPtrTy);
2793     Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t");
2794     Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy);
2795     Optional<QualType> ConstPthread_attr_tPtrTy =
2796         getPointerTy(getConstTy(Pthread_attr_tTy));
2797     Optional<QualType> ConstPthread_attr_tPtrRestrictTy =
2798         getRestrictTy(ConstPthread_attr_tPtrTy);
2799     Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t");
2800     Optional<QualType> ConstPthread_mutexattr_tPtrTy =
2801         getPointerTy(getConstTy(Pthread_mutexattr_tTy));
2802     Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy =
2803         getRestrictTy(ConstPthread_mutexattr_tPtrTy);
2804 
2805     QualType PthreadStartRoutineTy = getPointerTy(
2806         ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy,
2807                              FunctionProtoType::ExtProtoInfo()));
2808 
2809     // int pthread_cond_signal(pthread_cond_t *cond);
2810     // int pthread_cond_broadcast(pthread_cond_t *cond);
2811     addToFunctionSummaryMap(
2812         {"pthread_cond_signal", "pthread_cond_broadcast"},
2813         Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}),
2814         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2815 
2816     // int pthread_create(pthread_t *restrict thread,
2817     //                    const pthread_attr_t *restrict attr,
2818     //                    void *(*start_routine)(void*), void *restrict arg);
2819     addToFunctionSummaryMap(
2820         "pthread_create",
2821         Signature(ArgTypes{Pthread_tPtrRestrictTy,
2822                            ConstPthread_attr_tPtrRestrictTy,
2823                            PthreadStartRoutineTy, VoidPtrRestrictTy},
2824                   RetType{IntTy}),
2825         Summary(NoEvalCall)
2826             .ArgConstraint(NotNull(ArgNo(0)))
2827             .ArgConstraint(NotNull(ArgNo(2))));
2828 
2829     // int pthread_attr_destroy(pthread_attr_t *attr);
2830     // int pthread_attr_init(pthread_attr_t *attr);
2831     addToFunctionSummaryMap(
2832         {"pthread_attr_destroy", "pthread_attr_init"},
2833         Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}),
2834         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2835 
2836     // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
2837     //                               size_t *restrict stacksize);
2838     // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
2839     //                               size_t *restrict guardsize);
2840     addToFunctionSummaryMap(
2841         {"pthread_attr_getstacksize", "pthread_attr_getguardsize"},
2842         Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy},
2843                   RetType{IntTy}),
2844         Summary(NoEvalCall)
2845             .ArgConstraint(NotNull(ArgNo(0)))
2846             .ArgConstraint(NotNull(ArgNo(1))));
2847 
2848     // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
2849     // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
2850     addToFunctionSummaryMap(
2851         {"pthread_attr_setstacksize", "pthread_attr_setguardsize"},
2852         Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}),
2853         Summary(NoEvalCall)
2854             .ArgConstraint(NotNull(ArgNo(0)))
2855             .ArgConstraint(
2856                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
2857 
2858     // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
2859     //                        pthread_mutexattr_t *restrict attr);
2860     addToFunctionSummaryMap(
2861         "pthread_mutex_init",
2862         Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy,
2863                            ConstPthread_mutexattr_tPtrRestrictTy},
2864                   RetType{IntTy}),
2865         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2866 
2867     // int pthread_mutex_destroy(pthread_mutex_t *mutex);
2868     // int pthread_mutex_lock(pthread_mutex_t *mutex);
2869     // int pthread_mutex_trylock(pthread_mutex_t *mutex);
2870     // int pthread_mutex_unlock(pthread_mutex_t *mutex);
2871     addToFunctionSummaryMap(
2872         {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock",
2873          "pthread_mutex_unlock"},
2874         Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}),
2875         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2876   }
2877 
2878   // Functions for testing.
2879   if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
2880     addToFunctionSummaryMap(
2881         "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2882         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2883 
2884     // Test range values.
2885     addToFunctionSummaryMap(
2886         "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2887         Summary(EvalCallAsPure)
2888             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2889     addToFunctionSummaryMap(
2890         "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2891         Summary(EvalCallAsPure)
2892             .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2))));
2893     addToFunctionSummaryMap("__range_1_2__4_5",
2894                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
2895                             Summary(EvalCallAsPure)
2896                                 .ArgConstraint(ArgumentCondition(
2897                                     0U, WithinRange, Range({1, 2}, {4, 5}))));
2898 
2899     // Test range kind.
2900     addToFunctionSummaryMap(
2901         "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2902         Summary(EvalCallAsPure)
2903             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2904     addToFunctionSummaryMap(
2905         "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2906         Summary(EvalCallAsPure)
2907             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))));
2908 
2909     addToFunctionSummaryMap(
2910         "__two_constrained_args",
2911         Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
2912         Summary(EvalCallAsPure)
2913             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))
2914             .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1))));
2915     addToFunctionSummaryMap(
2916         "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2917         Summary(EvalCallAsPure)
2918             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))
2919             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2))));
2920     addToFunctionSummaryMap(
2921         "__defaultparam",
2922         Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}),
2923         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2924     addToFunctionSummaryMap(
2925         "__variadic",
2926         Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}),
2927         Summary(EvalCallAsPure)
2928             .ArgConstraint(NotNull(ArgNo(0)))
2929             .ArgConstraint(NotNull(ArgNo(1))));
2930     addToFunctionSummaryMap(
2931         "__buf_size_arg_constraint",
2932         Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}),
2933         Summary(EvalCallAsPure)
2934             .ArgConstraint(
2935                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))));
2936     addToFunctionSummaryMap(
2937         "__buf_size_arg_constraint_mul",
2938         Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}),
2939         Summary(EvalCallAsPure)
2940             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
2941                                       /*BufSizeMultiplier=*/ArgNo(2))));
2942     addToFunctionSummaryMap(
2943         "__buf_size_arg_constraint_concrete",
2944         Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}),
2945         Summary(EvalCallAsPure)
2946             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0),
2947                                       /*BufSize=*/BVF.getValue(10, IntTy))));
2948     addToFunctionSummaryMap(
2949         {"__test_restrict_param_0", "__test_restrict_param_1",
2950          "__test_restrict_param_2"},
2951         Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
2952         Summary(EvalCallAsPure));
2953   }
2954 
2955   SummariesInitialized = true;
2956 }
2957 
2958 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
2959   auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
2960   const AnalyzerOptions &Opts = mgr.getAnalyzerOptions();
2961   Checker->DisplayLoadedSummaries =
2962       Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries");
2963   Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX");
2964   Checker->ShouldAssumeControlledEnvironment =
2965       Opts.ShouldAssumeControlledEnvironment;
2966 }
2967 
2968 bool ento::shouldRegisterStdCLibraryFunctionsChecker(
2969     const CheckerManager &mgr) {
2970   return true;
2971 }
2972 
2973 #define REGISTER_CHECKER(name)                                                 \
2974   void ento::register##name(CheckerManager &mgr) {                             \
2975     StdLibraryFunctionsChecker *checker =                                      \
2976         mgr.getChecker<StdLibraryFunctionsChecker>();                          \
2977     checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
2978     checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
2979         mgr.getCurrentCheckerName();                                           \
2980   }                                                                            \
2981                                                                                \
2982   bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
2983 
2984 REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
2985 REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
2986