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