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