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