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 fileno(FILE *stream);
1680     addToFunctionSummaryMap(
1681         "fileno", Summary(ArgTypes{FilePtrTy}, RetType{IntTy}, NoEvalCall)
1682                       .ArgConstraint(NotNull(ArgNo(0))));
1683 
1684     // int fseeko(FILE *stream, off_t offset, int whence);
1685     addToFunctionSummaryMap(
1686         "fseeko",
1687         Summary(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}, NoEvalCall)
1688             .ArgConstraint(NotNull(ArgNo(0))));
1689 
1690     // off_t ftello(FILE *stream);
1691     addToFunctionSummaryMap(
1692         "ftello", Summary(ArgTypes{FilePtrTy}, RetType{Off_tTy}, NoEvalCall)
1693                       .ArgConstraint(NotNull(ArgNo(0))));
1694 
1695     Optional<RangeInt> Off_tMax = getMaxValue(Off_tTy);
1696     // void *mmap(void *addr, size_t length, int prot, int flags, int fd,
1697     // off_t offset);
1698     addToFunctionSummaryMap(
1699         "mmap",
1700         Summary(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
1701                 RetType{VoidPtrTy}, NoEvalCall)
1702             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1703             .ArgConstraint(
1704                 ArgumentCondition(4, WithinRange, Range(0, Off_tMax))));
1705 
1706     Optional<QualType> Off64_tTy = lookupTy("off64_t");
1707     Optional<RangeInt> Off64_tMax = getMaxValue(Off_tTy);
1708     // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
1709     // off64_t offset);
1710     addToFunctionSummaryMap(
1711         "mmap64",
1712         Summary(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
1713                 RetType{VoidPtrTy}, NoEvalCall)
1714             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1715             .ArgConstraint(
1716                 ArgumentCondition(4, WithinRange, Range(0, Off64_tMax))));
1717 
1718     // int pipe(int fildes[2]);
1719     addToFunctionSummaryMap(
1720         "pipe", Summary(ArgTypes{IntPtrTy}, RetType{IntTy}, NoEvalCall)
1721                     .ArgConstraint(NotNull(ArgNo(0))));
1722 
1723     // off_t lseek(int fildes, off_t offset, int whence);
1724     addToFunctionSummaryMap(
1725         "lseek",
1726         Summary(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}, NoEvalCall)
1727             .ArgConstraint(
1728                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1729 
1730     Optional<QualType> Ssize_tTy = lookupTy("ssize_t");
1731 
1732     // ssize_t readlink(const char *restrict path, char *restrict buf,
1733     //                  size_t bufsize);
1734     addToFunctionSummaryMap(
1735         "readlink",
1736         Summary(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
1737                 RetType{Ssize_tTy}, NoEvalCall)
1738             .ArgConstraint(NotNull(ArgNo(0)))
1739             .ArgConstraint(NotNull(ArgNo(1)))
1740             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1741                                       /*BufSize=*/ArgNo(2)))
1742             .ArgConstraint(
1743                 ArgumentCondition(2, WithinRange, Range(0, SizeMax))));
1744 
1745     // ssize_t readlinkat(int fd, const char *restrict path,
1746     //                    char *restrict buf, size_t bufsize);
1747     addToFunctionSummaryMap(
1748         "readlinkat",
1749         Summary(
1750             ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
1751             RetType{Ssize_tTy}, NoEvalCall)
1752             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1753             .ArgConstraint(NotNull(ArgNo(1)))
1754             .ArgConstraint(NotNull(ArgNo(2)))
1755             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
1756                                       /*BufSize=*/ArgNo(3)))
1757             .ArgConstraint(
1758                 ArgumentCondition(3, WithinRange, Range(0, SizeMax))));
1759 
1760     // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char
1761     // *newpath);
1762     addToFunctionSummaryMap("renameat", Summary(ArgTypes{IntTy, ConstCharPtrTy,
1763                                                          IntTy, ConstCharPtrTy},
1764                                                 RetType{IntTy}, NoEvalCall)
1765                                             .ArgConstraint(NotNull(ArgNo(1)))
1766                                             .ArgConstraint(NotNull(ArgNo(3))));
1767 
1768     // char *realpath(const char *restrict file_name,
1769     //                char *restrict resolved_name);
1770     addToFunctionSummaryMap(
1771         "realpath", Summary(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
1772                             RetType{CharPtrTy}, NoEvalCall)
1773                         .ArgConstraint(NotNull(ArgNo(0))));
1774 
1775     QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy));
1776 
1777     // int execv(const char *path, char *const argv[]);
1778     addToFunctionSummaryMap("execv",
1779                             Summary(ArgTypes{ConstCharPtrTy, CharPtrConstPtr},
1780                                     RetType{IntTy}, NoEvalCall)
1781                                 .ArgConstraint(NotNull(ArgNo(0))));
1782 
1783     // int execvp(const char *file, char *const argv[]);
1784     addToFunctionSummaryMap("execvp",
1785                             Summary(ArgTypes{ConstCharPtrTy, CharPtrConstPtr},
1786                                     RetType{IntTy}, NoEvalCall)
1787                                 .ArgConstraint(NotNull(ArgNo(0))));
1788 
1789     // int getopt(int argc, char * const argv[], const char *optstring);
1790     addToFunctionSummaryMap(
1791         "getopt",
1792         Summary(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
1793                 RetType{IntTy}, NoEvalCall)
1794             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1795             .ArgConstraint(NotNull(ArgNo(1)))
1796             .ArgConstraint(NotNull(ArgNo(2))));
1797 
1798     Optional<QualType> StructSockaddrTy = lookupTy("sockaddr");
1799     Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy);
1800     Optional<QualType> ConstStructSockaddrPtrTy =
1801         getPointerTy(getConstTy(StructSockaddrTy));
1802     Optional<QualType> StructSockaddrPtrRestrictTy =
1803         getRestrictTy(StructSockaddrPtrTy);
1804     Optional<QualType> ConstStructSockaddrPtrRestrictTy =
1805         getRestrictTy(ConstStructSockaddrPtrTy);
1806     Optional<QualType> Socklen_tTy = lookupTy("socklen_t");
1807     Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy);
1808     Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
1809     Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy);
1810 
1811     // In 'socket.h' of some libc implementations with C99, sockaddr parameter
1812     // is a transparent union of the underlying sockaddr_ family of pointers
1813     // instead of being a pointer to struct sockaddr. In these cases, the
1814     // standardized signature will not match, thus we try to match with another
1815     // signature that has the joker Irrelevant type. We also remove those
1816     // constraints which require pointer types for the sockaddr param.
1817     auto Accept =
1818         Summary(NoEvalCall)
1819             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
1820     if (!addToFunctionSummaryMap(
1821             "accept",
1822             // int accept(int socket, struct sockaddr *restrict address,
1823             //            socklen_t *restrict address_len);
1824             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
1825                                Socklen_tPtrRestrictTy},
1826                       RetType{IntTy}),
1827             Accept))
1828       addToFunctionSummaryMap(
1829           "accept",
1830           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
1831                     RetType{IntTy}),
1832           Accept);
1833 
1834     // int bind(int socket, const struct sockaddr *address, socklen_t
1835     //          address_len);
1836     if (!addToFunctionSummaryMap(
1837             "bind",
1838             Summary(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
1839                     RetType{IntTy}, NoEvalCall)
1840                 .ArgConstraint(
1841                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1842                 .ArgConstraint(NotNull(ArgNo(1)))
1843                 .ArgConstraint(
1844                     BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))
1845                 .ArgConstraint(
1846                     ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))))
1847       // Do not add constraints on sockaddr.
1848       addToFunctionSummaryMap(
1849           "bind", Summary(ArgTypes{IntTy, Irrelevant, Socklen_tTy},
1850                           RetType{IntTy}, NoEvalCall)
1851                       .ArgConstraint(
1852                           ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1853                       .ArgConstraint(ArgumentCondition(
1854                           2, WithinRange, Range(0, Socklen_tMax))));
1855 
1856     // int getpeername(int socket, struct sockaddr *restrict address,
1857     //                 socklen_t *restrict address_len);
1858     if (!addToFunctionSummaryMap(
1859             "getpeername", Summary(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
1860                                             Socklen_tPtrRestrictTy},
1861                                    RetType{IntTy}, NoEvalCall)
1862                                .ArgConstraint(ArgumentCondition(
1863                                    0, WithinRange, Range(0, IntMax)))
1864                                .ArgConstraint(NotNull(ArgNo(1)))
1865                                .ArgConstraint(NotNull(ArgNo(2)))))
1866       addToFunctionSummaryMap(
1867           "getpeername",
1868           Summary(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
1869                   RetType{IntTy}, NoEvalCall)
1870               .ArgConstraint(
1871                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1872 
1873     // int getsockname(int socket, struct sockaddr *restrict address,
1874     //                 socklen_t *restrict address_len);
1875     if (!addToFunctionSummaryMap(
1876             "getsockname", Summary(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
1877                                             Socklen_tPtrRestrictTy},
1878                                    RetType{IntTy}, NoEvalCall)
1879                                .ArgConstraint(ArgumentCondition(
1880                                    0, WithinRange, Range(0, IntMax)))
1881                                .ArgConstraint(NotNull(ArgNo(1)))
1882                                .ArgConstraint(NotNull(ArgNo(2)))))
1883       addToFunctionSummaryMap(
1884           "getsockname",
1885           Summary(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
1886                   RetType{IntTy}, NoEvalCall)
1887               .ArgConstraint(
1888                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1889 
1890     // int connect(int socket, const struct sockaddr *address, socklen_t
1891     //             address_len);
1892     if (!addToFunctionSummaryMap(
1893             "connect",
1894             Summary(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
1895                     RetType{IntTy}, NoEvalCall)
1896                 .ArgConstraint(
1897                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1898                 .ArgConstraint(NotNull(ArgNo(1)))))
1899       addToFunctionSummaryMap(
1900           "connect", Summary(ArgTypes{IntTy, Irrelevant, Socklen_tTy},
1901                              RetType{IntTy}, NoEvalCall)
1902                          .ArgConstraint(ArgumentCondition(0, WithinRange,
1903                                                           Range(0, IntMax))));
1904 
1905     auto Recvfrom =
1906         Summary(NoEvalCall)
1907             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1908             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1909                                       /*BufSize=*/ArgNo(2)));
1910     if (!addToFunctionSummaryMap(
1911             "recvfrom",
1912             // ssize_t recvfrom(int socket, void *restrict buffer,
1913             //                  size_t length,
1914             //                  int flags, struct sockaddr *restrict address,
1915             //                  socklen_t *restrict address_len);
1916             Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
1917                                StructSockaddrPtrRestrictTy,
1918                                Socklen_tPtrRestrictTy},
1919                       RetType{Ssize_tTy}),
1920             Recvfrom))
1921       addToFunctionSummaryMap(
1922           "recvfrom",
1923           Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
1924                              Irrelevant, Socklen_tPtrRestrictTy},
1925                     RetType{Ssize_tTy}),
1926           Recvfrom);
1927 
1928     auto Sendto =
1929         Summary(NoEvalCall)
1930             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1931             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1932                                       /*BufSize=*/ArgNo(2)));
1933     if (!addToFunctionSummaryMap(
1934             "sendto",
1935             // ssize_t sendto(int socket, const void *message, size_t length,
1936             //                int flags, const struct sockaddr *dest_addr,
1937             //                socklen_t dest_len);
1938             Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy,
1939                                ConstStructSockaddrPtrTy, Socklen_tTy},
1940                       RetType{Ssize_tTy}),
1941             Sendto))
1942       addToFunctionSummaryMap(
1943           "sendto",
1944           Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant,
1945                              Socklen_tTy},
1946                     RetType{Ssize_tTy}),
1947           Sendto);
1948 
1949     // int listen(int sockfd, int backlog);
1950     addToFunctionSummaryMap(
1951         "listen", Summary(ArgTypes{IntTy, IntTy}, RetType{IntTy}, NoEvalCall)
1952                       .ArgConstraint(
1953                           ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1954 
1955     // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
1956     addToFunctionSummaryMap(
1957         "recv",
1958         Summary(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy}, RetType{Ssize_tTy},
1959                 NoEvalCall)
1960             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1961             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1962                                       /*BufSize=*/ArgNo(2))));
1963 
1964     Optional<QualType> StructMsghdrTy = lookupTy("msghdr");
1965     Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy);
1966     Optional<QualType> ConstStructMsghdrPtrTy =
1967         getPointerTy(getConstTy(StructMsghdrTy));
1968 
1969     // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
1970     addToFunctionSummaryMap(
1971         "recvmsg", Summary(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
1972                            RetType{Ssize_tTy}, NoEvalCall)
1973                        .ArgConstraint(ArgumentCondition(0, WithinRange,
1974                                                         Range(0, IntMax))));
1975 
1976     // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
1977     addToFunctionSummaryMap(
1978         "sendmsg", Summary(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
1979                            RetType{Ssize_tTy}, NoEvalCall)
1980                        .ArgConstraint(ArgumentCondition(0, WithinRange,
1981                                                         Range(0, IntMax))));
1982 
1983     // int setsockopt(int socket, int level, int option_name,
1984     //                const void *option_value, socklen_t option_len);
1985     addToFunctionSummaryMap(
1986         "setsockopt",
1987         Summary(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
1988                 RetType{IntTy}, NoEvalCall)
1989             .ArgConstraint(NotNull(ArgNo(3)))
1990             .ArgConstraint(
1991                 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
1992             .ArgConstraint(
1993                 ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax))));
1994 
1995     // int getsockopt(int socket, int level, int option_name,
1996     //                void *restrict option_value,
1997     //                socklen_t *restrict option_len);
1998     addToFunctionSummaryMap(
1999         "getsockopt", Summary(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy,
2000                                        Socklen_tPtrRestrictTy},
2001                               RetType{IntTy}, NoEvalCall)
2002                           .ArgConstraint(NotNull(ArgNo(3)))
2003                           .ArgConstraint(NotNull(ArgNo(4))));
2004 
2005     // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
2006     addToFunctionSummaryMap(
2007         "send",
2008         Summary(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy},
2009                 RetType{Ssize_tTy}, NoEvalCall)
2010             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2011             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2012                                       /*BufSize=*/ArgNo(2))));
2013 
2014     // int socketpair(int domain, int type, int protocol, int sv[2]);
2015     addToFunctionSummaryMap("socketpair",
2016                             Summary(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy},
2017                                     RetType{IntTy}, NoEvalCall)
2018                                 .ArgConstraint(NotNull(ArgNo(3))));
2019 
2020     // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
2021     //                 char *restrict node, socklen_t nodelen,
2022     //                 char *restrict service,
2023     //                 socklen_t servicelen, int flags);
2024     //
2025     // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr
2026     // parameter is never handled as a transparent union in netdb.h
2027     addToFunctionSummaryMap(
2028         "getnameinfo",
2029         Summary(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy,
2030                          CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy,
2031                          Socklen_tTy, IntTy},
2032                 RetType{IntTy}, NoEvalCall)
2033             .ArgConstraint(
2034                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
2035             .ArgConstraint(
2036                 ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax)))
2037             .ArgConstraint(
2038                 BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3)))
2039             .ArgConstraint(
2040                 ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax)))
2041             .ArgConstraint(
2042                 BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
2043             .ArgConstraint(
2044                 ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax))));
2045 
2046     Optional<QualType> StructUtimbufTy = lookupTy("utimbuf");
2047     Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy);
2048 
2049     // int utime(const char *filename, struct utimbuf *buf);
2050     addToFunctionSummaryMap(
2051         "utime", Summary(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy},
2052                          RetType{IntTy}, NoEvalCall)
2053                      .ArgConstraint(NotNull(ArgNo(0))));
2054 
2055     Optional<QualType> StructTimespecTy = lookupTy("timespec");
2056     Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy);
2057     Optional<QualType> ConstStructTimespecPtrTy =
2058         getPointerTy(getConstTy(StructTimespecTy));
2059 
2060     // int futimens(int fd, const struct timespec times[2]);
2061     addToFunctionSummaryMap(
2062         "futimens", Summary(ArgTypes{IntTy, ConstStructTimespecPtrTy},
2063                             RetType{IntTy}, NoEvalCall)
2064                         .ArgConstraint(ArgumentCondition(0, WithinRange,
2065                                                          Range(0, IntMax))));
2066 
2067     // int utimensat(int dirfd, const char *pathname,
2068     //               const struct timespec times[2], int flags);
2069     addToFunctionSummaryMap("utimensat",
2070                             Summary(ArgTypes{IntTy, ConstCharPtrTy,
2071                                              ConstStructTimespecPtrTy, IntTy},
2072                                     RetType{IntTy}, NoEvalCall)
2073                                 .ArgConstraint(NotNull(ArgNo(1))));
2074 
2075     Optional<QualType> StructTimevalTy = lookupTy("timeval");
2076     Optional<QualType> ConstStructTimevalPtrTy =
2077         getPointerTy(getConstTy(StructTimevalTy));
2078 
2079     // int utimes(const char *filename, const struct timeval times[2]);
2080     addToFunctionSummaryMap(
2081         "utimes", Summary(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
2082                           RetType{IntTy}, NoEvalCall)
2083                       .ArgConstraint(NotNull(ArgNo(0))));
2084 
2085     // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
2086     addToFunctionSummaryMap(
2087         "nanosleep",
2088         Summary(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
2089                 RetType{IntTy}, NoEvalCall)
2090             .ArgConstraint(NotNull(ArgNo(0))));
2091 
2092     Optional<QualType> Time_tTy = lookupTy("time_t");
2093     Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy));
2094     Optional<QualType> ConstTime_tPtrRestrictTy =
2095         getRestrictTy(ConstTime_tPtrTy);
2096 
2097     Optional<QualType> StructTmTy = lookupTy("tm");
2098     Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy);
2099     Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy);
2100     Optional<QualType> ConstStructTmPtrTy =
2101         getPointerTy(getConstTy(StructTmTy));
2102     Optional<QualType> ConstStructTmPtrRestrictTy =
2103         getRestrictTy(ConstStructTmPtrTy);
2104 
2105     // struct tm * localtime(const time_t *tp);
2106     addToFunctionSummaryMap(
2107         "localtime",
2108         Summary(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}, NoEvalCall)
2109             .ArgConstraint(NotNull(ArgNo(0))));
2110 
2111     // struct tm *localtime_r(const time_t *restrict timer,
2112     //                        struct tm *restrict result);
2113     addToFunctionSummaryMap(
2114         "localtime_r",
2115         Summary(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2116                 RetType{StructTmPtrTy}, NoEvalCall)
2117             .ArgConstraint(NotNull(ArgNo(0)))
2118             .ArgConstraint(NotNull(ArgNo(1))));
2119 
2120     // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
2121     addToFunctionSummaryMap(
2122         "asctime_r",
2123         Summary(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
2124                 RetType{CharPtrTy}, NoEvalCall)
2125             .ArgConstraint(NotNull(ArgNo(0)))
2126             .ArgConstraint(NotNull(ArgNo(1)))
2127             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2128                                       /*MinBufSize=*/BVF.getValue(26, IntTy))));
2129 
2130     // char *ctime_r(const time_t *timep, char *buf);
2131     addToFunctionSummaryMap("ctime_r",
2132                             Summary(ArgTypes{ConstTime_tPtrTy, CharPtrTy},
2133                                     RetType{CharPtrTy}, NoEvalCall)
2134                                 .ArgConstraint(NotNull(ArgNo(0)))
2135                                 .ArgConstraint(NotNull(ArgNo(1)))
2136                                 .ArgConstraint(BufferSize(
2137                                     /*Buffer=*/ArgNo(1),
2138                                     /*MinBufSize=*/BVF.getValue(26, IntTy))));
2139 
2140     // struct tm *gmtime_r(const time_t *restrict timer,
2141     //                     struct tm *restrict result);
2142     addToFunctionSummaryMap(
2143         "gmtime_r",
2144         Summary(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2145                 RetType{StructTmPtrTy}, NoEvalCall)
2146             .ArgConstraint(NotNull(ArgNo(0)))
2147             .ArgConstraint(NotNull(ArgNo(1))));
2148 
2149     // struct tm * gmtime(const time_t *tp);
2150     addToFunctionSummaryMap(
2151         "gmtime",
2152         Summary(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}, NoEvalCall)
2153             .ArgConstraint(NotNull(ArgNo(0))));
2154 
2155     Optional<QualType> Clockid_tTy = lookupTy("clockid_t");
2156 
2157     // int clock_gettime(clockid_t clock_id, struct timespec *tp);
2158     addToFunctionSummaryMap("clock_gettime",
2159                             Summary(ArgTypes{Clockid_tTy, StructTimespecPtrTy},
2160                                     RetType{IntTy}, NoEvalCall)
2161                                 .ArgConstraint(NotNull(ArgNo(1))));
2162 
2163     Optional<QualType> StructItimervalTy = lookupTy("itimerval");
2164     Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy);
2165 
2166     // int getitimer(int which, struct itimerval *curr_value);
2167     addToFunctionSummaryMap("getitimer",
2168                             Summary(ArgTypes{IntTy, StructItimervalPtrTy},
2169                                     RetType{IntTy}, NoEvalCall)
2170                                 .ArgConstraint(NotNull(ArgNo(1))));
2171 
2172     Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
2173     Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy);
2174     Optional<QualType> Pthread_tTy = lookupTy("pthread_t");
2175     Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy);
2176     Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy);
2177     Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t");
2178     Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy);
2179     Optional<QualType> Pthread_mutex_tPtrRestrictTy =
2180         getRestrictTy(Pthread_mutex_tPtrTy);
2181     Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t");
2182     Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy);
2183     Optional<QualType> ConstPthread_attr_tPtrTy =
2184         getPointerTy(getConstTy(Pthread_attr_tTy));
2185     Optional<QualType> ConstPthread_attr_tPtrRestrictTy =
2186         getRestrictTy(ConstPthread_attr_tPtrTy);
2187     Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t");
2188     Optional<QualType> ConstPthread_mutexattr_tPtrTy =
2189         getPointerTy(getConstTy(Pthread_mutexattr_tTy));
2190     Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy =
2191         getRestrictTy(ConstPthread_mutexattr_tPtrTy);
2192 
2193     QualType PthreadStartRoutineTy = getPointerTy(
2194         ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy,
2195                              FunctionProtoType::ExtProtoInfo()));
2196 
2197     // int pthread_cond_signal(pthread_cond_t *cond);
2198     // int pthread_cond_broadcast(pthread_cond_t *cond);
2199     addToFunctionSummaryMap(
2200         {"pthread_cond_signal", "pthread_cond_broadcast"},
2201         Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}),
2202         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2203 
2204     // int pthread_create(pthread_t *restrict thread,
2205     //                    const pthread_attr_t *restrict attr,
2206     //                    void *(*start_routine)(void*), void *restrict arg);
2207     addToFunctionSummaryMap(
2208         "pthread_create",
2209         Signature(ArgTypes{Pthread_tPtrRestrictTy,
2210                            ConstPthread_attr_tPtrRestrictTy,
2211                            PthreadStartRoutineTy, VoidPtrRestrictTy},
2212                   RetType{IntTy}),
2213         Summary(NoEvalCall)
2214             .ArgConstraint(NotNull(ArgNo(0)))
2215             .ArgConstraint(NotNull(ArgNo(2))));
2216 
2217     // int pthread_attr_destroy(pthread_attr_t *attr);
2218     // int pthread_attr_init(pthread_attr_t *attr);
2219     addToFunctionSummaryMap(
2220         {"pthread_attr_destroy", "pthread_attr_init"},
2221         Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}),
2222         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2223 
2224     // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
2225     //                               size_t *restrict stacksize);
2226     // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
2227     //                               size_t *restrict guardsize);
2228     addToFunctionSummaryMap(
2229         {"pthread_attr_getstacksize", "pthread_attr_getguardsize"},
2230         Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy},
2231                   RetType{IntTy}),
2232         Summary(NoEvalCall)
2233             .ArgConstraint(NotNull(ArgNo(0)))
2234             .ArgConstraint(NotNull(ArgNo(1))));
2235 
2236     // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
2237     // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
2238     addToFunctionSummaryMap(
2239         {"pthread_attr_setstacksize", "pthread_attr_setguardsize"},
2240         Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}),
2241         Summary(NoEvalCall)
2242             .ArgConstraint(NotNull(ArgNo(0)))
2243             .ArgConstraint(
2244                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
2245 
2246     // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
2247     //                        pthread_mutexattr_t *restrict attr);
2248     addToFunctionSummaryMap(
2249         "pthread_mutex_init",
2250         Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy,
2251                            ConstPthread_mutexattr_tPtrRestrictTy},
2252                   RetType{IntTy}),
2253         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2254 
2255     // int pthread_mutex_destroy(pthread_mutex_t *mutex);
2256     // int pthread_mutex_lock(pthread_mutex_t *mutex);
2257     // int pthread_mutex_trylock(pthread_mutex_t *mutex);
2258     // int pthread_mutex_unlock(pthread_mutex_t *mutex);
2259     addToFunctionSummaryMap(
2260         {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock",
2261          "pthread_mutex_unlock"},
2262         Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}),
2263         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2264   }
2265 
2266   // Functions for testing.
2267   if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
2268     addToFunctionSummaryMap(
2269         "__two_constrained_args",
2270         Summary(ArgTypes{IntTy, IntTy}, RetType{IntTy}, EvalCallAsPure)
2271             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))
2272             .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1))));
2273     addToFunctionSummaryMap(
2274         "__arg_constrained_twice",
2275         Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure)
2276             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))
2277             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2))));
2278     addToFunctionSummaryMap(
2279         "__defaultparam",
2280         Summary(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}, EvalCallAsPure)
2281             .ArgConstraint(NotNull(ArgNo(0))));
2282     addToFunctionSummaryMap("__variadic",
2283                             Summary(ArgTypes{VoidPtrTy, ConstCharPtrTy},
2284                                     RetType{IntTy}, EvalCallAsPure)
2285                                 .ArgConstraint(NotNull(ArgNo(0)))
2286                                 .ArgConstraint(NotNull(ArgNo(1))));
2287     addToFunctionSummaryMap(
2288         "__buf_size_arg_constraint",
2289         Summary(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy},
2290                 EvalCallAsPure)
2291             .ArgConstraint(
2292                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))));
2293     addToFunctionSummaryMap(
2294         "__buf_size_arg_constraint_mul",
2295         Summary(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy},
2296                 EvalCallAsPure)
2297             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
2298                                       /*BufSizeMultiplier=*/ArgNo(2))));
2299     addToFunctionSummaryMap(
2300         "__buf_size_arg_constraint_concrete",
2301         Summary(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}, EvalCallAsPure)
2302             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0),
2303                                       /*BufSize=*/BVF.getValue(10, IntTy))));
2304     addToFunctionSummaryMap(
2305         {"__test_restrict_param_0", "__test_restrict_param_1",
2306          "__test_restrict_param_2"},
2307         Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
2308         Summary(EvalCallAsPure));
2309   }
2310 }
2311 
2312 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
2313   auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
2314   Checker->DisplayLoadedSummaries =
2315       mgr.getAnalyzerOptions().getCheckerBooleanOption(
2316           Checker, "DisplayLoadedSummaries");
2317   Checker->ModelPOSIX =
2318       mgr.getAnalyzerOptions().getCheckerBooleanOption(Checker, "ModelPOSIX");
2319 }
2320 
2321 bool ento::shouldRegisterStdCLibraryFunctionsChecker(
2322     const CheckerManager &mgr) {
2323   return true;
2324 }
2325 
2326 #define REGISTER_CHECKER(name)                                                 \
2327   void ento::register##name(CheckerManager &mgr) {                             \
2328     StdLibraryFunctionsChecker *checker =                                      \
2329         mgr.getChecker<StdLibraryFunctionsChecker>();                          \
2330     checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
2331     checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
2332         mgr.getCurrentCheckerName();                                           \
2333   }                                                                            \
2334                                                                                \
2335   bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
2336 
2337 REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
2338 REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
2339