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