1bba497fbSArtem Dergachev //=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===//
2bba497fbSArtem Dergachev //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bba497fbSArtem Dergachev //
7bba497fbSArtem Dergachev //===----------------------------------------------------------------------===//
8bba497fbSArtem Dergachev //
9bba497fbSArtem Dergachev // This checker improves modeling of a few simple library functions.
10bba497fbSArtem Dergachev //
11f5086b38SGabor Marton // This checker provides a specification format - `Summary' - and
12bba497fbSArtem Dergachev // contains descriptions of some library functions in this format. Each
13bba497fbSArtem Dergachev // specification contains a list of branches for splitting the program state
14bba497fbSArtem Dergachev // upon call, and range constraints on argument and return-value symbols that
15bba497fbSArtem Dergachev // are satisfied on each branch. This spec can be expanded to include more
16bba497fbSArtem Dergachev // items, like external effects of the function.
17bba497fbSArtem Dergachev //
18bba497fbSArtem Dergachev // The main difference between this approach and the body farms technique is
19bba497fbSArtem Dergachev // in more explicit control over how many branches are produced. For example,
20bba497fbSArtem Dergachev // consider standard C function `ispunct(int x)', which returns a non-zero value
21bba497fbSArtem Dergachev // iff `x' is a punctuation character, that is, when `x' is in range
22bba497fbSArtem Dergachev //   ['!', '/']   [':', '@']  U  ['[', '\`']  U  ['{', '~'].
23f5086b38SGabor Marton // `Summary' provides only two branches for this function. However,
24bba497fbSArtem Dergachev // any attempt to describe this range with if-statements in the body farm
25bba497fbSArtem Dergachev // would result in many more branches. Because each branch needs to be analyzed
26bba497fbSArtem Dergachev // independently, this significantly reduces performance. Additionally,
27bba497fbSArtem Dergachev // once we consider a branch on which `x' is in range, say, ['!', '/'],
28bba497fbSArtem Dergachev // we assume that such branch is an important separate path through the program,
29bba497fbSArtem Dergachev // which may lead to false positives because considering this particular path
30bba497fbSArtem Dergachev // was not consciously intended, and therefore it might have been unreachable.
31bba497fbSArtem Dergachev //
32f5086b38SGabor Marton // This checker uses eval::Call for modeling pure functions (functions without
33f5086b38SGabor Marton // side effets), for which their `Summary' is a precise model. This avoids
34f5086b38SGabor Marton // unnecessary invalidation passes. Conflicts with other checkers are unlikely
35f5086b38SGabor Marton // because if the function has no other effects, other checkers would probably
36f5086b38SGabor Marton // never want to improve upon the modeling done by this checker.
37bba497fbSArtem Dergachev //
38f5086b38SGabor Marton // Non-pure functions, for which only partial improvement over the default
39bba497fbSArtem Dergachev // behavior is expected, are modeled via check::PostCall, non-intrusively.
40bba497fbSArtem Dergachev //
41bba497fbSArtem Dergachev // The following standard C functions are currently supported:
42bba497fbSArtem Dergachev //
4325bbe234SZurab Tsinadze //   fgetc      getline   isdigit   isupper     toascii
44bba497fbSArtem Dergachev //   fread      isalnum   isgraph   isxdigit
45bba497fbSArtem Dergachev //   fwrite     isalpha   islower   read
46bba497fbSArtem Dergachev //   getc       isascii   isprint   write
4725bbe234SZurab Tsinadze //   getchar    isblank   ispunct   toupper
4825bbe234SZurab Tsinadze //   getdelim   iscntrl   isspace   tolower
49bba497fbSArtem Dergachev //
50bba497fbSArtem Dergachev //===----------------------------------------------------------------------===//
51bba497fbSArtem Dergachev 
5276a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
5394061df6SGabor Marton #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
54bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/Checker.h"
55bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/CheckerManager.h"
56bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
57bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
58536456a7SGabor Marton #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
599b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
60a7cb951fSGabor Marton #include "llvm/ADT/SmallString.h"
61a7cb951fSGabor Marton #include "llvm/ADT/StringExtras.h"
62a7cb951fSGabor Marton 
63a7cb951fSGabor Marton #include <string>
64bba497fbSArtem Dergachev 
65bba497fbSArtem Dergachev using namespace clang;
66bba497fbSArtem Dergachev using namespace clang::ento;
67bba497fbSArtem Dergachev 
68bba497fbSArtem Dergachev namespace {
6994061df6SGabor Marton class StdLibraryFunctionsChecker
7094061df6SGabor Marton     : public Checker<check::PreCall, check::PostCall, eval::Call> {
7116506d78SGabor Marton 
7216506d78SGabor Marton   class Summary;
73bba497fbSArtem Dergachev 
74bba497fbSArtem Dergachev   /// Specify how much the analyzer engine should entrust modeling this function
75bba497fbSArtem Dergachev   /// to us. If he doesn't, he performs additional invalidations.
76f5086b38SGabor Marton   enum InvalidationKind { NoEvalCall, EvalCallAsPure };
77bba497fbSArtem Dergachev 
7847fec16cSArtem Dergachev   // The universal integral type to use in value range descriptions.
7947fec16cSArtem Dergachev   // Unsigned to make sure overflows are well-defined.
80f5086b38SGabor Marton   typedef uint64_t RangeInt;
8147fec16cSArtem Dergachev 
82bba497fbSArtem Dergachev   /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
83bba497fbSArtem Dergachev   /// a non-negative integer, which less than 5 and not equal to 2. For
84bba497fbSArtem Dergachev   /// `ComparesToArgument', holds information about how exactly to compare to
85bba497fbSArtem Dergachev   /// the argument.
86f5086b38SGabor Marton   typedef std::vector<std::pair<RangeInt, RangeInt>> IntRangeVector;
87bba497fbSArtem Dergachev 
88bba497fbSArtem Dergachev   /// A reference to an argument or return value by its number.
89bba497fbSArtem Dergachev   /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
90bba497fbSArtem Dergachev   /// obviously uint32_t should be enough for all practical purposes.
91f5086b38SGabor Marton   typedef uint32_t ArgNo;
92c6b8484eSGabor Marton   static const ArgNo Ret;
93bba497fbSArtem Dergachev 
94a7cb951fSGabor Marton   /// Returns the string representation of an argument index.
95a7cb951fSGabor Marton   /// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
96a7cb951fSGabor Marton   static SmallString<8> getArgDesc(ArgNo);
97a7cb951fSGabor Marton 
9894061df6SGabor Marton   class ValueConstraint;
9994061df6SGabor Marton 
10094061df6SGabor Marton   // Pointer to the ValueConstraint. We need a copyable, polymorphic and
10194061df6SGabor Marton   // default initialize able type (vector needs that). A raw pointer was good,
10294061df6SGabor Marton   // however, we cannot default initialize that. unique_ptr makes the Summary
10394061df6SGabor Marton   // class non-copyable, therefore not an option. Releasing the copyability
10494061df6SGabor Marton   // requirement would render the initialization of the Summary map infeasible.
10594061df6SGabor Marton   using ValueConstraintPtr = std::shared_ptr<ValueConstraint>;
10694061df6SGabor Marton 
107c6b8484eSGabor Marton   /// Polymorphic base class that represents a constraint on a given argument
108c6b8484eSGabor Marton   /// (or return value) of a function. Derived classes implement different kind
109c6b8484eSGabor Marton   /// of constraints, e.g range constraints or correlation between two
110c6b8484eSGabor Marton   /// arguments.
111c6b8484eSGabor Marton   class ValueConstraint {
112c6b8484eSGabor Marton   public:
113c6b8484eSGabor Marton     ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {}
114c6b8484eSGabor Marton     virtual ~ValueConstraint() {}
115c6b8484eSGabor Marton     /// Apply the effects of the constraint on the given program state. If null
116c6b8484eSGabor Marton     /// is returned then the constraint is not feasible.
117c6b8484eSGabor Marton     virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
118bd03ef19SGabor Marton                                   const Summary &Summary,
119bd03ef19SGabor Marton                                   CheckerContext &C) const = 0;
12094061df6SGabor Marton     virtual ValueConstraintPtr negate() const {
12194061df6SGabor Marton       llvm_unreachable("Not implemented");
12294061df6SGabor Marton     };
12316506d78SGabor Marton 
12416506d78SGabor Marton     // Check whether the constraint is malformed or not. It is malformed if the
12516506d78SGabor Marton     // specified argument has a mismatch with the given FunctionDecl (e.g. the
12616506d78SGabor Marton     // arg number is out-of-range of the function's argument list).
12716506d78SGabor Marton     bool checkValidity(const FunctionDecl *FD) const {
12816506d78SGabor Marton       const bool ValidArg = ArgN == Ret || ArgN < FD->getNumParams();
12916506d78SGabor Marton       assert(ValidArg && "Arg out of range!");
13016506d78SGabor Marton       if (!ValidArg)
13116506d78SGabor Marton         return false;
13216506d78SGabor Marton       // Subclasses may further refine the validation.
13316506d78SGabor Marton       return checkSpecificValidity(FD);
13416506d78SGabor Marton     }
135c6b8484eSGabor Marton     ArgNo getArgNo() const { return ArgN; }
136c6b8484eSGabor Marton 
1374b99f9c7SGabor Marton     // Return those arguments that should be tracked when we report a bug. By
1384b99f9c7SGabor Marton     // default it is the argument that is constrained, however, in some special
1394b99f9c7SGabor Marton     // cases we need to track other arguments as well. E.g. a buffer size might
1404b99f9c7SGabor Marton     // be encoded in another argument.
1414b99f9c7SGabor Marton     virtual std::vector<ArgNo> getArgsToTrack() const { return {ArgN}; }
1424b99f9c7SGabor Marton 
143a97648b9SGabor Marton     virtual StringRef getName() const = 0;
144a97648b9SGabor Marton 
145a7cb951fSGabor Marton     // Give a description that explains the constraint to the user. Used when
146a7cb951fSGabor Marton     // the bug is reported.
147a7cb951fSGabor Marton     virtual std::string describe(ProgramStateRef State,
148a7cb951fSGabor Marton                                  const Summary &Summary) const {
149a7cb951fSGabor Marton       // There are some descendant classes that are not used as argument
150a7cb951fSGabor Marton       // constraints, e.g. ComparisonConstraint. In that case we can safely
151a7cb951fSGabor Marton       // ignore the implementation of this function.
152a7cb951fSGabor Marton       llvm_unreachable("Not implemented");
153a7cb951fSGabor Marton     }
154a7cb951fSGabor Marton 
155c6b8484eSGabor Marton   protected:
156c6b8484eSGabor Marton     ArgNo ArgN; // Argument to which we apply the constraint.
15716506d78SGabor Marton 
15816506d78SGabor Marton     /// Do polymorphic sanity check on the constraint.
15916506d78SGabor Marton     virtual bool checkSpecificValidity(const FunctionDecl *FD) const {
16016506d78SGabor Marton       return true;
16116506d78SGabor Marton     }
162c6b8484eSGabor Marton   };
163c6b8484eSGabor Marton 
164c6b8484eSGabor Marton   /// Given a range, should the argument stay inside or outside this range?
165c6b8484eSGabor Marton   enum RangeKind { OutOfRange, WithinRange };
166c6b8484eSGabor Marton 
167a787a4edSGabor Marton   /// Encapsulates a range on a single symbol.
168c6b8484eSGabor Marton   class RangeConstraint : public ValueConstraint {
169a787a4edSGabor Marton     RangeKind Kind;
170a787a4edSGabor Marton     // A range is formed as a set of intervals (sub-ranges).
171a787a4edSGabor Marton     // E.g. {['A', 'Z'], ['a', 'z']}
172a787a4edSGabor Marton     //
173a787a4edSGabor Marton     // The default constructed RangeConstraint has an empty range set, applying
174a787a4edSGabor Marton     // such constraint does not involve any assumptions, thus the State remains
175a787a4edSGabor Marton     // unchanged. This is meaningful, if the range is dependent on a looked up
176a787a4edSGabor Marton     // type (e.g. [0, Socklen_tMax]). If the type is not found, then the range
177a787a4edSGabor Marton     // is default initialized to be empty.
178a787a4edSGabor Marton     IntRangeVector Ranges;
179bba497fbSArtem Dergachev 
180bba497fbSArtem Dergachev   public:
181a97648b9SGabor Marton     StringRef getName() const override { return "Range"; }
182a787a4edSGabor Marton     RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges)
183a787a4edSGabor Marton         : ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {}
184bba497fbSArtem Dergachev 
185a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
186a7cb951fSGabor Marton                          const Summary &Summary) const override;
187a7cb951fSGabor Marton 
188a787a4edSGabor Marton     const IntRangeVector &getRanges() const { return Ranges; }
189bba497fbSArtem Dergachev 
190bba497fbSArtem Dergachev   private:
191f5086b38SGabor Marton     ProgramStateRef applyAsOutOfRange(ProgramStateRef State,
192f5086b38SGabor Marton                                       const CallEvent &Call,
193f5086b38SGabor Marton                                       const Summary &Summary) const;
194f5086b38SGabor Marton     ProgramStateRef applyAsWithinRange(ProgramStateRef State,
195f5086b38SGabor Marton                                        const CallEvent &Call,
196f5086b38SGabor Marton                                        const Summary &Summary) const;
19725bbe234SZurab Tsinadze 
198bba497fbSArtem Dergachev   public:
199bba497fbSArtem Dergachev     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
200bd03ef19SGabor Marton                           const Summary &Summary,
201bd03ef19SGabor Marton                           CheckerContext &C) const override {
202bba497fbSArtem Dergachev       switch (Kind) {
203bba497fbSArtem Dergachev       case OutOfRange:
204bba497fbSArtem Dergachev         return applyAsOutOfRange(State, Call, Summary);
205bba497fbSArtem Dergachev       case WithinRange:
206bba497fbSArtem Dergachev         return applyAsWithinRange(State, Call, Summary);
207bba497fbSArtem Dergachev       }
208c6b8484eSGabor Marton       llvm_unreachable("Unknown range kind!");
209bba497fbSArtem Dergachev     }
21094061df6SGabor Marton 
21194061df6SGabor Marton     ValueConstraintPtr negate() const override {
21294061df6SGabor Marton       RangeConstraint Tmp(*this);
21394061df6SGabor Marton       switch (Kind) {
21494061df6SGabor Marton       case OutOfRange:
21594061df6SGabor Marton         Tmp.Kind = WithinRange;
21694061df6SGabor Marton         break;
21794061df6SGabor Marton       case WithinRange:
21894061df6SGabor Marton         Tmp.Kind = OutOfRange;
21994061df6SGabor Marton         break;
22094061df6SGabor Marton       }
22194061df6SGabor Marton       return std::make_shared<RangeConstraint>(Tmp);
22294061df6SGabor Marton     }
22316506d78SGabor Marton 
22416506d78SGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
22516506d78SGabor Marton       const bool ValidArg =
22616506d78SGabor Marton           getArgType(FD, ArgN)->isIntegralType(FD->getASTContext());
22716506d78SGabor Marton       assert(ValidArg &&
22816506d78SGabor Marton              "This constraint should be applied on an integral type");
22916506d78SGabor Marton       return ValidArg;
23016506d78SGabor Marton     }
231bba497fbSArtem Dergachev   };
232bba497fbSArtem Dergachev 
233c6b8484eSGabor Marton   class ComparisonConstraint : public ValueConstraint {
234c6b8484eSGabor Marton     BinaryOperator::Opcode Opcode;
235c6b8484eSGabor Marton     ArgNo OtherArgN;
236c6b8484eSGabor Marton 
237c6b8484eSGabor Marton   public:
238a97648b9SGabor Marton     virtual StringRef getName() const override { return "Comparison"; };
239c6b8484eSGabor Marton     ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode,
240c6b8484eSGabor Marton                          ArgNo OtherArgN)
241c6b8484eSGabor Marton         : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {}
242c6b8484eSGabor Marton     ArgNo getOtherArgNo() const { return OtherArgN; }
243c6b8484eSGabor Marton     BinaryOperator::Opcode getOpcode() const { return Opcode; }
244c6b8484eSGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
245bd03ef19SGabor Marton                           const Summary &Summary,
246bd03ef19SGabor Marton                           CheckerContext &C) const override;
247c6b8484eSGabor Marton   };
248c6b8484eSGabor Marton 
249ededa65dSGabor Marton   class NotNullConstraint : public ValueConstraint {
250ededa65dSGabor Marton     using ValueConstraint::ValueConstraint;
251ededa65dSGabor Marton     // This variable has a role when we negate the constraint.
252ededa65dSGabor Marton     bool CannotBeNull = true;
253ededa65dSGabor Marton 
254ededa65dSGabor Marton   public:
255a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
256a7cb951fSGabor Marton                          const Summary &Summary) const override;
257a97648b9SGabor Marton     StringRef getName() const override { return "NonNull"; }
258ededa65dSGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
259bd03ef19SGabor Marton                           const Summary &Summary,
260bd03ef19SGabor Marton                           CheckerContext &C) const override {
261ededa65dSGabor Marton       SVal V = getArgSVal(Call, getArgNo());
262defd95efSVince Bridgers       if (V.isUndef())
263defd95efSVince Bridgers         return State;
264defd95efSVince Bridgers 
265ededa65dSGabor Marton       DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>();
266ededa65dSGabor Marton       if (!L.getAs<Loc>())
267ededa65dSGabor Marton         return State;
268ededa65dSGabor Marton 
269ededa65dSGabor Marton       return State->assume(L, CannotBeNull);
270ededa65dSGabor Marton     }
271ededa65dSGabor Marton 
272ededa65dSGabor Marton     ValueConstraintPtr negate() const override {
273ededa65dSGabor Marton       NotNullConstraint Tmp(*this);
274ededa65dSGabor Marton       Tmp.CannotBeNull = !this->CannotBeNull;
275ededa65dSGabor Marton       return std::make_shared<NotNullConstraint>(Tmp);
276ededa65dSGabor Marton     }
27716506d78SGabor Marton 
27816506d78SGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
27916506d78SGabor Marton       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
28016506d78SGabor Marton       assert(ValidArg &&
28116506d78SGabor Marton              "This constraint should be applied only on a pointer type");
28216506d78SGabor Marton       return ValidArg;
28316506d78SGabor Marton     }
284ededa65dSGabor Marton   };
285ededa65dSGabor Marton 
286f0b9dbcfSGabor Marton   // Represents a buffer argument with an additional size constraint. The
287f0b9dbcfSGabor Marton   // constraint may be a concrete value, or a symbolic value in an argument.
288f0b9dbcfSGabor Marton   // Example 1. Concrete value as the minimum buffer size.
289f0b9dbcfSGabor Marton   //   char *asctime_r(const struct tm *restrict tm, char *restrict buf);
290f0b9dbcfSGabor Marton   //   // `buf` size must be at least 26 bytes according the POSIX standard.
291f0b9dbcfSGabor Marton   // Example 2. Argument as a buffer size.
292bd03ef19SGabor Marton   //   ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
293f0b9dbcfSGabor Marton   // Example 3. The size is computed as a multiplication of other args.
29441928c97SGabor Marton   //   size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
29541928c97SGabor Marton   //   // Here, ptr is the buffer, and its minimum size is `size * nmemb`.
296bd03ef19SGabor Marton   class BufferSizeConstraint : public ValueConstraint {
297f0b9dbcfSGabor Marton     // The concrete value which is the minimum size for the buffer.
298f0b9dbcfSGabor Marton     llvm::Optional<llvm::APSInt> ConcreteSize;
299bd03ef19SGabor Marton     // The argument which holds the size of the buffer.
300f0b9dbcfSGabor Marton     llvm::Optional<ArgNo> SizeArgN;
30141928c97SGabor Marton     // The argument which is a multiplier to size. This is set in case of
30241928c97SGabor Marton     // `fread` like functions where the size is computed as a multiplication of
30341928c97SGabor Marton     // two arguments.
30441928c97SGabor Marton     llvm::Optional<ArgNo> SizeMultiplierArgN;
305bd03ef19SGabor Marton     // The operator we use in apply. This is negated in negate().
306bd03ef19SGabor Marton     BinaryOperator::Opcode Op = BO_LE;
307bd03ef19SGabor Marton 
308bd03ef19SGabor Marton   public:
309a97648b9SGabor Marton     StringRef getName() const override { return "BufferSize"; }
310f0b9dbcfSGabor Marton     BufferSizeConstraint(ArgNo Buffer, llvm::APSInt BufMinSize)
311f0b9dbcfSGabor Marton         : ValueConstraint(Buffer), ConcreteSize(BufMinSize) {}
312bd03ef19SGabor Marton     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize)
313bd03ef19SGabor Marton         : ValueConstraint(Buffer), SizeArgN(BufSize) {}
31441928c97SGabor Marton     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier)
31541928c97SGabor Marton         : ValueConstraint(Buffer), SizeArgN(BufSize),
31641928c97SGabor Marton           SizeMultiplierArgN(BufSizeMultiplier) {}
31741928c97SGabor Marton 
3184b99f9c7SGabor Marton     std::vector<ArgNo> getArgsToTrack() const override {
3194b99f9c7SGabor Marton       std::vector<ArgNo> Result{ArgN};
3204b99f9c7SGabor Marton       if (SizeArgN)
3214b99f9c7SGabor Marton         Result.push_back(*SizeArgN);
3224b99f9c7SGabor Marton       if (SizeMultiplierArgN)
3234b99f9c7SGabor Marton         Result.push_back(*SizeMultiplierArgN);
3244b99f9c7SGabor Marton       return Result;
3254b99f9c7SGabor Marton     }
3264b99f9c7SGabor Marton 
327a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
328a7cb951fSGabor Marton                          const Summary &Summary) const override;
329a7cb951fSGabor Marton 
330bd03ef19SGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
331bd03ef19SGabor Marton                           const Summary &Summary,
332bd03ef19SGabor Marton                           CheckerContext &C) const override {
33341928c97SGabor Marton       SValBuilder &SvalBuilder = C.getSValBuilder();
334bd03ef19SGabor Marton       // The buffer argument.
335bd03ef19SGabor Marton       SVal BufV = getArgSVal(Call, getArgNo());
336f0b9dbcfSGabor Marton 
337f0b9dbcfSGabor Marton       // Get the size constraint.
338f0b9dbcfSGabor Marton       const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() {
339f0b9dbcfSGabor Marton         if (ConcreteSize) {
340f0b9dbcfSGabor Marton           return SVal(SvalBuilder.makeIntVal(*ConcreteSize));
341a7cb951fSGabor Marton         }
342a7cb951fSGabor Marton         assert(SizeArgN && "The constraint must be either a concrete value or "
343a7cb951fSGabor Marton                            "encoded in an argument.");
344bd03ef19SGabor Marton         // The size argument.
345f0b9dbcfSGabor Marton         SVal SizeV = getArgSVal(Call, *SizeArgN);
34641928c97SGabor Marton         // Multiply with another argument if given.
34741928c97SGabor Marton         if (SizeMultiplierArgN) {
34841928c97SGabor Marton           SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
34941928c97SGabor Marton           SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
350f0b9dbcfSGabor Marton                                         Summary.getArgType(*SizeArgN));
35141928c97SGabor Marton         }
352f0b9dbcfSGabor Marton         return SizeV;
353f0b9dbcfSGabor Marton       }();
354f0b9dbcfSGabor Marton 
355bd03ef19SGabor Marton       // The dynamic size of the buffer argument, got from the analyzer engine.
3569b3df78bSCharusso       SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
357bd03ef19SGabor Marton 
358bd03ef19SGabor Marton       SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize,
359bd03ef19SGabor Marton                                             SvalBuilder.getContext().BoolTy);
360bd03ef19SGabor Marton       if (auto F = Feasible.getAs<DefinedOrUnknownSVal>())
361bd03ef19SGabor Marton         return State->assume(*F, true);
362bd03ef19SGabor Marton 
363bd03ef19SGabor Marton       // We can get here only if the size argument or the dynamic size is
364bd03ef19SGabor Marton       // undefined. But the dynamic size should never be undefined, only
365bd03ef19SGabor Marton       // unknown. So, here, the size of the argument is undefined, i.e. we
366bd03ef19SGabor Marton       // cannot apply the constraint. Actually, other checkers like
367bd03ef19SGabor Marton       // CallAndMessage should catch this situation earlier, because we call a
368bd03ef19SGabor Marton       // function with an uninitialized argument.
369bd03ef19SGabor Marton       llvm_unreachable("Size argument or the dynamic size is Undefined");
370bd03ef19SGabor Marton     }
371bd03ef19SGabor Marton 
372bd03ef19SGabor Marton     ValueConstraintPtr negate() const override {
373bd03ef19SGabor Marton       BufferSizeConstraint Tmp(*this);
374bd03ef19SGabor Marton       Tmp.Op = BinaryOperator::negateComparisonOp(Op);
375bd03ef19SGabor Marton       return std::make_shared<BufferSizeConstraint>(Tmp);
376bd03ef19SGabor Marton     }
3773ff220deSGabor Marton 
3783ff220deSGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
3793ff220deSGabor Marton       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
3803ff220deSGabor Marton       assert(ValidArg &&
3813ff220deSGabor Marton              "This constraint should be applied only on a pointer type");
3823ff220deSGabor Marton       return ValidArg;
3833ff220deSGabor Marton     }
384bd03ef19SGabor Marton   };
385bd03ef19SGabor Marton 
386c6b8484eSGabor Marton   /// The complete list of constraints that defines a single branch.
387c6b8484eSGabor Marton   typedef std::vector<ValueConstraintPtr> ConstraintSet;
388bba497fbSArtem Dergachev 
389a787a4edSGabor Marton   using ArgTypes = std::vector<Optional<QualType>>;
390a787a4edSGabor Marton   using RetType = Optional<QualType>;
39116506d78SGabor Marton 
39216506d78SGabor Marton   // A placeholder type, we use it whenever we do not care about the concrete
39316506d78SGabor Marton   // type in a Signature.
39416506d78SGabor Marton   const QualType Irrelevant{};
39516506d78SGabor Marton   bool static isIrrelevant(QualType T) { return T.isNull(); }
39616506d78SGabor Marton 
39716506d78SGabor Marton   // The signature of a function we want to describe with a summary. This is a
39816506d78SGabor Marton   // concessive signature, meaning there may be irrelevant types in the
39916506d78SGabor Marton   // signature which we do not check against a function with concrete types.
400a787a4edSGabor Marton   // All types in the spec need to be canonical.
401a787a4edSGabor Marton   class Signature {
402a787a4edSGabor Marton     using ArgQualTypes = std::vector<QualType>;
403a787a4edSGabor Marton     ArgQualTypes ArgTys;
4043ff220deSGabor Marton     QualType RetTy;
405a787a4edSGabor Marton     // True if any component type is not found by lookup.
406a787a4edSGabor Marton     bool Invalid = false;
407a787a4edSGabor Marton 
408a787a4edSGabor Marton   public:
409a787a4edSGabor Marton     // Construct a signature from optional types. If any of the optional types
410a787a4edSGabor Marton     // are not set then the signature will be invalid.
411a787a4edSGabor Marton     Signature(ArgTypes ArgTys, RetType RetTy) {
412a787a4edSGabor Marton       for (Optional<QualType> Arg : ArgTys) {
413a787a4edSGabor Marton         if (!Arg) {
414a787a4edSGabor Marton           Invalid = true;
415a787a4edSGabor Marton           return;
416a787a4edSGabor Marton         } else {
417a787a4edSGabor Marton           assertArgTypeSuitableForSignature(*Arg);
418a787a4edSGabor Marton           this->ArgTys.push_back(*Arg);
419a787a4edSGabor Marton         }
420a787a4edSGabor Marton       }
421a787a4edSGabor Marton       if (!RetTy) {
422a787a4edSGabor Marton         Invalid = true;
423a787a4edSGabor Marton         return;
424a787a4edSGabor Marton       } else {
425a787a4edSGabor Marton         assertRetTypeSuitableForSignature(*RetTy);
426a787a4edSGabor Marton         this->RetTy = *RetTy;
42716506d78SGabor Marton       }
42816506d78SGabor Marton     }
4293ff220deSGabor Marton 
430a787a4edSGabor Marton     bool isInvalid() const { return Invalid; }
43116506d78SGabor Marton     bool matches(const FunctionDecl *FD) const;
43216506d78SGabor Marton 
43316506d78SGabor Marton   private:
43416506d78SGabor Marton     static void assertArgTypeSuitableForSignature(QualType T) {
43516506d78SGabor Marton       assert((T.isNull() || !T->isVoidType()) &&
43616506d78SGabor Marton              "We should have no void types in the spec");
43716506d78SGabor Marton       assert((T.isNull() || T.isCanonical()) &&
43816506d78SGabor Marton              "We should only have canonical types in the spec");
43916506d78SGabor Marton     }
44016506d78SGabor Marton     static void assertRetTypeSuitableForSignature(QualType T) {
44116506d78SGabor Marton       assert((T.isNull() || T.isCanonical()) &&
44216506d78SGabor Marton              "We should only have canonical types in the spec");
44316506d78SGabor Marton     }
44416506d78SGabor Marton   };
44516506d78SGabor Marton 
44616506d78SGabor Marton   static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) {
44716506d78SGabor Marton     assert(FD && "Function must be set");
44816506d78SGabor Marton     QualType T = (ArgN == Ret)
44916506d78SGabor Marton                      ? FD->getReturnType().getCanonicalType()
45016506d78SGabor Marton                      : FD->getParamDecl(ArgN)->getType().getCanonicalType();
45116506d78SGabor Marton     return T;
45216506d78SGabor Marton   }
45316506d78SGabor Marton 
454c6b8484eSGabor Marton   using Cases = std::vector<ConstraintSet>;
455f5086b38SGabor Marton 
45616506d78SGabor Marton   /// A summary includes information about
45716506d78SGabor Marton   ///   * function prototype (signature)
45894061df6SGabor Marton   ///   * approach to invalidation,
45994061df6SGabor Marton   ///   * a list of branches - a list of list of ranges -
46094061df6SGabor Marton   ///     A branch represents a path in the exploded graph of a function (which
46194061df6SGabor Marton   ///     is a tree). So, a branch is a series of assumptions. In other words,
46294061df6SGabor Marton   ///     branches represent split states and additional assumptions on top of
46394061df6SGabor Marton   ///     the splitting assumption.
46494061df6SGabor Marton   ///     For example, consider the branches in `isalpha(x)`
46594061df6SGabor Marton   ///       Branch 1)
46694061df6SGabor Marton   ///         x is in range ['A', 'Z'] or in ['a', 'z']
46794061df6SGabor Marton   ///         then the return value is not 0. (I.e. out-of-range [0, 0])
46894061df6SGabor Marton   ///       Branch 2)
46994061df6SGabor Marton   ///         x is out-of-range ['A', 'Z'] and out-of-range ['a', 'z']
47094061df6SGabor Marton   ///         then the return value is 0.
47194061df6SGabor Marton   ///   * a list of argument constraints, that must be true on every branch.
47294061df6SGabor Marton   ///     If these constraints are not satisfied that means a fatal error
47394061df6SGabor Marton   ///     usually resulting in undefined behaviour.
47416506d78SGabor Marton   ///
47516506d78SGabor Marton   /// Application of a summary:
47616506d78SGabor Marton   ///   The signature and argument constraints together contain information
47716506d78SGabor Marton   ///   about which functions are handled by the summary. The signature can use
47816506d78SGabor Marton   ///   "wildcards", i.e. Irrelevant types. Irrelevant type of a parameter in
47916506d78SGabor Marton   ///   a signature means that type is not compared to the type of the parameter
48016506d78SGabor Marton   ///   in the found FunctionDecl. Argument constraints may specify additional
48116506d78SGabor Marton   ///   rules for the given parameter's type, those rules are checked once the
48216506d78SGabor Marton   ///   signature is matched.
48316506d78SGabor Marton   class Summary {
484f5086b38SGabor Marton     const InvalidationKind InvalidationKd;
485c6b8484eSGabor Marton     Cases CaseConstraints;
486c6b8484eSGabor Marton     ConstraintSet ArgConstraints;
487f5086b38SGabor Marton 
48816506d78SGabor Marton     // The function to which the summary applies. This is set after lookup and
48916506d78SGabor Marton     // match to the signature.
49016506d78SGabor Marton     const FunctionDecl *FD = nullptr;
49116506d78SGabor Marton 
49216506d78SGabor Marton   public:
4933ff220deSGabor Marton     Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {}
4943ff220deSGabor Marton 
495c6b8484eSGabor Marton     Summary &Case(ConstraintSet &&CS) {
496c6b8484eSGabor Marton       CaseConstraints.push_back(std::move(CS));
497f5086b38SGabor Marton       return *this;
498f5086b38SGabor Marton     }
499b40b3196SGabor Marton     Summary &Case(const ConstraintSet &CS) {
500b40b3196SGabor Marton       CaseConstraints.push_back(CS);
501b40b3196SGabor Marton       return *this;
502b40b3196SGabor Marton     }
50394061df6SGabor Marton     Summary &ArgConstraint(ValueConstraintPtr VC) {
504a97648b9SGabor Marton       assert(VC->getArgNo() != Ret &&
505a97648b9SGabor Marton              "Arg constraint should not refer to the return value");
50694061df6SGabor Marton       ArgConstraints.push_back(VC);
50794061df6SGabor Marton       return *this;
50894061df6SGabor Marton     }
509bba497fbSArtem Dergachev 
51016506d78SGabor Marton     InvalidationKind getInvalidationKd() const { return InvalidationKd; }
51116506d78SGabor Marton     const Cases &getCaseConstraints() const { return CaseConstraints; }
51216506d78SGabor Marton     const ConstraintSet &getArgConstraints() const { return ArgConstraints; }
513bba497fbSArtem Dergachev 
514f5086b38SGabor Marton     QualType getArgType(ArgNo ArgN) const {
51516506d78SGabor Marton       return StdLibraryFunctionsChecker::getArgType(FD, ArgN);
516bba497fbSArtem Dergachev     }
517bba497fbSArtem Dergachev 
51816506d78SGabor Marton     // Returns true if the summary should be applied to the given function.
51916506d78SGabor Marton     // And if yes then store the function declaration.
52011d2e63aSGabor Marton     bool matchesAndSet(const Signature &Sign, const FunctionDecl *FD) {
52111d2e63aSGabor Marton       bool Result = Sign.matches(FD) && validateByConstraints(FD);
52216506d78SGabor Marton       if (Result) {
52316506d78SGabor Marton         assert(!this->FD && "FD must not be set more than once");
52416506d78SGabor Marton         this->FD = FD;
52516506d78SGabor Marton       }
52616506d78SGabor Marton       return Result;
52716506d78SGabor Marton     }
52816506d78SGabor Marton 
52916506d78SGabor Marton   private:
53016506d78SGabor Marton     // Once we know the exact type of the function then do sanity check on all
53116506d78SGabor Marton     // the given constraints.
53216506d78SGabor Marton     bool validateByConstraints(const FunctionDecl *FD) const {
53316506d78SGabor Marton       for (const ConstraintSet &Case : CaseConstraints)
53416506d78SGabor Marton         for (const ValueConstraintPtr &Constraint : Case)
53516506d78SGabor Marton           if (!Constraint->checkValidity(FD))
53616506d78SGabor Marton             return false;
53716506d78SGabor Marton       for (const ValueConstraintPtr &Constraint : ArgConstraints)
53816506d78SGabor Marton         if (!Constraint->checkValidity(FD))
53916506d78SGabor Marton           return false;
54016506d78SGabor Marton       return true;
54116506d78SGabor Marton     }
542bba497fbSArtem Dergachev   };
543bba497fbSArtem Dergachev 
544bba497fbSArtem Dergachev   // The map of all functions supported by the checker. It is initialized
545bba497fbSArtem Dergachev   // lazily, and it doesn't change after initialization.
54662e747f6SGabor Marton   using FunctionSummaryMapType = llvm::DenseMap<const FunctionDecl *, Summary>;
54762e747f6SGabor Marton   mutable FunctionSummaryMapType FunctionSummaryMap;
548bba497fbSArtem Dergachev 
54994061df6SGabor Marton   mutable std::unique_ptr<BugType> BT_InvalidArg;
550c7635040SValeriy Savchenko   mutable bool SummariesInitialized = false;
55194061df6SGabor Marton 
552f5086b38SGabor Marton   static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) {
553f5086b38SGabor Marton     return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN);
554bba497fbSArtem Dergachev   }
555bba497fbSArtem Dergachev 
556bba497fbSArtem Dergachev public:
55794061df6SGabor Marton   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
558bba497fbSArtem Dergachev   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
55944820630SArtem Dergachev   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
560bba497fbSArtem Dergachev 
5611525232eSGabor Marton   enum CheckKind {
5621525232eSGabor Marton     CK_StdCLibraryFunctionArgsChecker,
5631525232eSGabor Marton     CK_StdCLibraryFunctionsTesterChecker,
5641525232eSGabor Marton     CK_NumCheckKinds
5651525232eSGabor Marton   };
56694061df6SGabor Marton   DefaultBool ChecksEnabled[CK_NumCheckKinds];
56794061df6SGabor Marton   CheckerNameRef CheckNames[CK_NumCheckKinds];
56894061df6SGabor Marton 
569ff4492c8SGabor Marton   bool DisplayLoadedSummaries = false;
570db4d5f70SGabor Marton   bool ModelPOSIX = false;
571*edde4efcSBalazs Benics   bool ShouldAssumeControlledEnvironment = false;
572ff4492c8SGabor Marton 
573bba497fbSArtem Dergachev private:
574f5086b38SGabor Marton   Optional<Summary> findFunctionSummary(const FunctionDecl *FD,
575bba497fbSArtem Dergachev                                         CheckerContext &C) const;
57694061df6SGabor Marton   Optional<Summary> findFunctionSummary(const CallEvent &Call,
57794061df6SGabor Marton                                         CheckerContext &C) const;
578bba497fbSArtem Dergachev 
579536456a7SGabor Marton   void initFunctionSummaries(CheckerContext &C) const;
58094061df6SGabor Marton 
58194061df6SGabor Marton   void reportBug(const CallEvent &Call, ExplodedNode *N,
582a7cb951fSGabor Marton                  const ValueConstraint *VC, const Summary &Summary,
583a7cb951fSGabor Marton                  CheckerContext &C) const {
58494061df6SGabor Marton     if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
58594061df6SGabor Marton       return;
586a97648b9SGabor Marton     std::string Msg =
587a97648b9SGabor Marton         (Twine("Function argument constraint is not satisfied, constraint: ") +
588a7cb951fSGabor Marton          VC->getName().data())
589a97648b9SGabor Marton             .str();
59094061df6SGabor Marton     if (!BT_InvalidArg)
59194061df6SGabor Marton       BT_InvalidArg = std::make_unique<BugType>(
59294061df6SGabor Marton           CheckNames[CK_StdCLibraryFunctionArgsChecker],
59394061df6SGabor Marton           "Unsatisfied argument constraints", categories::LogicError);
59494061df6SGabor Marton     auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
5954b99f9c7SGabor Marton 
5964b99f9c7SGabor Marton     for (ArgNo ArgN : VC->getArgsToTrack())
5974b99f9c7SGabor Marton       bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
598a97648b9SGabor Marton 
599a97648b9SGabor Marton     // Highlight the range of the argument that was violated.
600a97648b9SGabor Marton     R->addRange(Call.getArgSourceRange(VC->getArgNo()));
601a97648b9SGabor Marton 
602a7cb951fSGabor Marton     // Describe the argument constraint in a note.
603a7cb951fSGabor Marton     R->addNote(VC->describe(C.getState(), Summary), R->getLocation(),
604a7cb951fSGabor Marton                Call.getArgSourceRange(VC->getArgNo()));
605a7cb951fSGabor Marton 
60694061df6SGabor Marton     C.emitReport(std::move(R));
60794061df6SGabor Marton   }
608bba497fbSArtem Dergachev };
609c6b8484eSGabor Marton 
610c6b8484eSGabor Marton const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret =
611c6b8484eSGabor Marton     std::numeric_limits<ArgNo>::max();
612c6b8484eSGabor Marton 
613bba497fbSArtem Dergachev } // end of anonymous namespace
614bba497fbSArtem Dergachev 
615a7cb951fSGabor Marton static BasicValueFactory &getBVF(ProgramStateRef State) {
616a7cb951fSGabor Marton   ProgramStateManager &Mgr = State->getStateManager();
617a7cb951fSGabor Marton   SValBuilder &SVB = Mgr.getSValBuilder();
618a7cb951fSGabor Marton   return SVB.getBasicValueFactory();
619a7cb951fSGabor Marton }
620a7cb951fSGabor Marton 
621a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::NotNullConstraint::describe(
622a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
623a7cb951fSGabor Marton   SmallString<48> Result;
624a7cb951fSGabor Marton   Result += "The ";
625a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
626a7cb951fSGabor Marton   Result += " should not be NULL";
627a7cb951fSGabor Marton   return Result.c_str();
628a7cb951fSGabor Marton }
629a7cb951fSGabor Marton 
630a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::RangeConstraint::describe(
631a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
632a7cb951fSGabor Marton 
633a7cb951fSGabor Marton   BasicValueFactory &BVF = getBVF(State);
634a7cb951fSGabor Marton 
635a7cb951fSGabor Marton   QualType T = Summary.getArgType(getArgNo());
636a7cb951fSGabor Marton   SmallString<48> Result;
637a7cb951fSGabor Marton   Result += "The ";
638a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
639a7cb951fSGabor Marton   Result += " should be ";
640a7cb951fSGabor Marton 
641a7cb951fSGabor Marton   // Range kind as a string.
642a7cb951fSGabor Marton   Kind == OutOfRange ? Result += "out of" : Result += "within";
643a7cb951fSGabor Marton 
644a7cb951fSGabor Marton   // Get the range values as a string.
645a7cb951fSGabor Marton   Result += " the range ";
646a7cb951fSGabor Marton   if (Ranges.size() > 1)
647a7cb951fSGabor Marton     Result += "[";
648a7cb951fSGabor Marton   unsigned I = Ranges.size();
649a7cb951fSGabor Marton   for (const std::pair<RangeInt, RangeInt> &R : Ranges) {
650a7cb951fSGabor Marton     Result += "[";
651a7cb951fSGabor Marton     const llvm::APSInt &Min = BVF.getValue(R.first, T);
652a7cb951fSGabor Marton     const llvm::APSInt &Max = BVF.getValue(R.second, T);
653a7cb951fSGabor Marton     Min.toString(Result);
654a7cb951fSGabor Marton     Result += ", ";
655a7cb951fSGabor Marton     Max.toString(Result);
656a7cb951fSGabor Marton     Result += "]";
657a7cb951fSGabor Marton     if (--I > 0)
658a7cb951fSGabor Marton       Result += ", ";
659a7cb951fSGabor Marton   }
660a7cb951fSGabor Marton   if (Ranges.size() > 1)
661a7cb951fSGabor Marton     Result += "]";
662a7cb951fSGabor Marton 
663a7cb951fSGabor Marton   return Result.c_str();
664a7cb951fSGabor Marton }
665a7cb951fSGabor Marton 
666a7cb951fSGabor Marton SmallString<8>
667a7cb951fSGabor Marton StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) {
668a7cb951fSGabor Marton   SmallString<8> Result;
669a7cb951fSGabor Marton   Result += std::to_string(ArgN + 1);
670a7cb951fSGabor Marton   Result += llvm::getOrdinalSuffix(ArgN + 1);
671a7cb951fSGabor Marton   Result += " arg";
672a7cb951fSGabor Marton   return Result;
673a7cb951fSGabor Marton }
674a7cb951fSGabor Marton 
675a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
676a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
677a7cb951fSGabor Marton   SmallString<96> Result;
678a7cb951fSGabor Marton   Result += "The size of the ";
679a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
680a7cb951fSGabor Marton   Result += " should be equal to or less than the value of ";
681a7cb951fSGabor Marton   if (ConcreteSize) {
682a7cb951fSGabor Marton     ConcreteSize->toString(Result);
683a7cb951fSGabor Marton   } else if (SizeArgN) {
684a7cb951fSGabor Marton     Result += "the ";
685a7cb951fSGabor Marton     Result += getArgDesc(*SizeArgN);
686a7cb951fSGabor Marton     if (SizeMultiplierArgN) {
687a7cb951fSGabor Marton       Result += " times the ";
688a7cb951fSGabor Marton       Result += getArgDesc(*SizeMultiplierArgN);
689a7cb951fSGabor Marton     }
690a7cb951fSGabor Marton   }
691a7cb951fSGabor Marton   return Result.c_str();
692a7cb951fSGabor Marton }
693a7cb951fSGabor Marton 
694c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange(
695bba497fbSArtem Dergachev     ProgramStateRef State, const CallEvent &Call,
696f5086b38SGabor Marton     const Summary &Summary) const {
697a787a4edSGabor Marton   if (Ranges.empty())
698a787a4edSGabor Marton     return State;
699bba497fbSArtem Dergachev 
700bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
701bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
702bba497fbSArtem Dergachev   BasicValueFactory &BVF = SVB.getBasicValueFactory();
703bba497fbSArtem Dergachev   ConstraintManager &CM = Mgr.getConstraintManager();
70416506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
705bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
706bba497fbSArtem Dergachev 
707bba497fbSArtem Dergachev   if (auto N = V.getAs<NonLoc>()) {
708f5086b38SGabor Marton     const IntRangeVector &R = getRanges();
709bba497fbSArtem Dergachev     size_t E = R.size();
710bba497fbSArtem Dergachev     for (size_t I = 0; I != E; ++I) {
711bba497fbSArtem Dergachev       const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
712bba497fbSArtem Dergachev       const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
713bba497fbSArtem Dergachev       assert(Min <= Max);
7143f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
715bba497fbSArtem Dergachev       if (!State)
716bba497fbSArtem Dergachev         break;
717bba497fbSArtem Dergachev     }
718bba497fbSArtem Dergachev   }
719bba497fbSArtem Dergachev 
720bba497fbSArtem Dergachev   return State;
721bba497fbSArtem Dergachev }
722bba497fbSArtem Dergachev 
723c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange(
724bba497fbSArtem Dergachev     ProgramStateRef State, const CallEvent &Call,
725f5086b38SGabor Marton     const Summary &Summary) const {
726a787a4edSGabor Marton   if (Ranges.empty())
727a787a4edSGabor Marton     return State;
728bba497fbSArtem Dergachev 
729bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
730bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
731bba497fbSArtem Dergachev   BasicValueFactory &BVF = SVB.getBasicValueFactory();
732bba497fbSArtem Dergachev   ConstraintManager &CM = Mgr.getConstraintManager();
73316506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
734bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
735bba497fbSArtem Dergachev 
736bba497fbSArtem Dergachev   // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
737bba497fbSArtem Dergachev   // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
738bba497fbSArtem Dergachev   // and then cut away all holes in R one by one.
739536456a7SGabor Marton   //
740536456a7SGabor Marton   // E.g. consider a range list R as [A, B] and [C, D]
741536456a7SGabor Marton   // -------+--------+------------------+------------+----------->
742536456a7SGabor Marton   //        A        B                  C            D
743536456a7SGabor Marton   // Then we assume that the value is not in [-inf, A - 1],
744536456a7SGabor Marton   // then not in [D + 1, +inf], then not in [B + 1, C - 1]
745bba497fbSArtem Dergachev   if (auto N = V.getAs<NonLoc>()) {
746f5086b38SGabor Marton     const IntRangeVector &R = getRanges();
747bba497fbSArtem Dergachev     size_t E = R.size();
748bba497fbSArtem Dergachev 
749bba497fbSArtem Dergachev     const llvm::APSInt &MinusInf = BVF.getMinValue(T);
750bba497fbSArtem Dergachev     const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
751bba497fbSArtem Dergachev 
75226b0a9d8SArtem Dergachev     const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
753bba497fbSArtem Dergachev     if (Left != PlusInf) {
754bba497fbSArtem Dergachev       assert(MinusInf <= Left);
7553f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
756bba497fbSArtem Dergachev       if (!State)
757bba497fbSArtem Dergachev         return nullptr;
758bba497fbSArtem Dergachev     }
759bba497fbSArtem Dergachev 
76026b0a9d8SArtem Dergachev     const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
761bba497fbSArtem Dergachev     if (Right != MinusInf) {
762bba497fbSArtem Dergachev       assert(Right <= PlusInf);
7633f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
764bba497fbSArtem Dergachev       if (!State)
765bba497fbSArtem Dergachev         return nullptr;
766bba497fbSArtem Dergachev     }
767bba497fbSArtem Dergachev 
768bba497fbSArtem Dergachev     for (size_t I = 1; I != E; ++I) {
76926b0a9d8SArtem Dergachev       const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
77026b0a9d8SArtem Dergachev       const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
771536456a7SGabor Marton       if (Min <= Max) {
7723f8c3fa7SDominic Chen         State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
773bba497fbSArtem Dergachev         if (!State)
774bba497fbSArtem Dergachev           return nullptr;
775bba497fbSArtem Dergachev       }
776bba497fbSArtem Dergachev     }
777536456a7SGabor Marton   }
778bba497fbSArtem Dergachev 
779bba497fbSArtem Dergachev   return State;
780bba497fbSArtem Dergachev }
781bba497fbSArtem Dergachev 
782c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply(
783bd03ef19SGabor Marton     ProgramStateRef State, const CallEvent &Call, const Summary &Summary,
784bd03ef19SGabor Marton     CheckerContext &C) const {
785bba497fbSArtem Dergachev 
786bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
787bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
788bba497fbSArtem Dergachev   QualType CondT = SVB.getConditionType();
78916506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
790bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
791bba497fbSArtem Dergachev 
792bba497fbSArtem Dergachev   BinaryOperator::Opcode Op = getOpcode();
793f5086b38SGabor Marton   ArgNo OtherArg = getOtherArgNo();
794bba497fbSArtem Dergachev   SVal OtherV = getArgSVal(Call, OtherArg);
79516506d78SGabor Marton   QualType OtherT = Summary.getArgType(OtherArg);
796bba497fbSArtem Dergachev   // Note: we avoid integral promotion for comparison.
797bba497fbSArtem Dergachev   OtherV = SVB.evalCast(OtherV, T, OtherT);
798bba497fbSArtem Dergachev   if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
799bba497fbSArtem Dergachev                        .getAs<DefinedOrUnknownSVal>())
800bba497fbSArtem Dergachev     State = State->assume(*CompV, true);
801bba497fbSArtem Dergachev   return State;
802bba497fbSArtem Dergachev }
803bba497fbSArtem Dergachev 
80494061df6SGabor Marton void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
80594061df6SGabor Marton                                               CheckerContext &C) const {
80694061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
80794061df6SGabor Marton   if (!FoundSummary)
80894061df6SGabor Marton     return;
80994061df6SGabor Marton 
81094061df6SGabor Marton   const Summary &Summary = *FoundSummary;
81194061df6SGabor Marton   ProgramStateRef State = C.getState();
81294061df6SGabor Marton 
8131525232eSGabor Marton   ProgramStateRef NewState = State;
81416506d78SGabor Marton   for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) {
81516506d78SGabor Marton     ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C);
81616506d78SGabor Marton     ProgramStateRef FailureSt =
81716506d78SGabor Marton         Constraint->negate()->apply(NewState, Call, Summary, C);
81894061df6SGabor Marton     // The argument constraint is not satisfied.
81994061df6SGabor Marton     if (FailureSt && !SuccessSt) {
8201525232eSGabor Marton       if (ExplodedNode *N = C.generateErrorNode(NewState))
821a7cb951fSGabor Marton         reportBug(Call, N, Constraint.get(), Summary, C);
82294061df6SGabor Marton       break;
82394061df6SGabor Marton     } else {
8241525232eSGabor Marton       // We will apply the constraint even if we cannot reason about the
8251525232eSGabor Marton       // argument. This means both SuccessSt and FailureSt can be true. If we
8261525232eSGabor Marton       // weren't applying the constraint that would mean that symbolic
8271525232eSGabor Marton       // execution continues on a code whose behaviour is undefined.
82894061df6SGabor Marton       assert(SuccessSt);
8291525232eSGabor Marton       NewState = SuccessSt;
83094061df6SGabor Marton     }
83194061df6SGabor Marton   }
8321525232eSGabor Marton   if (NewState && NewState != State)
8331525232eSGabor Marton     C.addTransition(NewState);
83494061df6SGabor Marton }
83594061df6SGabor Marton 
836bba497fbSArtem Dergachev void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
837bba497fbSArtem Dergachev                                                CheckerContext &C) const {
83894061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
839bba497fbSArtem Dergachev   if (!FoundSummary)
840bba497fbSArtem Dergachev     return;
841bba497fbSArtem Dergachev 
842c6b8484eSGabor Marton   // Now apply the constraints.
843f5086b38SGabor Marton   const Summary &Summary = *FoundSummary;
844bba497fbSArtem Dergachev   ProgramStateRef State = C.getState();
845bba497fbSArtem Dergachev 
846f5086b38SGabor Marton   // Apply case/branch specifications.
84716506d78SGabor Marton   for (const ConstraintSet &Case : Summary.getCaseConstraints()) {
848bba497fbSArtem Dergachev     ProgramStateRef NewState = State;
84916506d78SGabor Marton     for (const ValueConstraintPtr &Constraint : Case) {
85016506d78SGabor Marton       NewState = Constraint->apply(NewState, Call, Summary, C);
851bba497fbSArtem Dergachev       if (!NewState)
852bba497fbSArtem Dergachev         break;
853bba497fbSArtem Dergachev     }
854bba497fbSArtem Dergachev 
855bba497fbSArtem Dergachev     if (NewState && NewState != State)
856bba497fbSArtem Dergachev       C.addTransition(NewState);
857bba497fbSArtem Dergachev   }
858bba497fbSArtem Dergachev }
859bba497fbSArtem Dergachev 
86044820630SArtem Dergachev bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
861bba497fbSArtem Dergachev                                           CheckerContext &C) const {
86294061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
863bba497fbSArtem Dergachev   if (!FoundSummary)
864bba497fbSArtem Dergachev     return false;
865bba497fbSArtem Dergachev 
866f5086b38SGabor Marton   const Summary &Summary = *FoundSummary;
86716506d78SGabor Marton   switch (Summary.getInvalidationKd()) {
868bba497fbSArtem Dergachev   case EvalCallAsPure: {
869bba497fbSArtem Dergachev     ProgramStateRef State = C.getState();
870bba497fbSArtem Dergachev     const LocationContext *LC = C.getLocationContext();
871879c12d9SSimon Pilgrim     const auto *CE = cast<CallExpr>(Call.getOriginExpr());
872bba497fbSArtem Dergachev     SVal V = C.getSValBuilder().conjureSymbolVal(
873bba497fbSArtem Dergachev         CE, LC, CE->getType().getCanonicalType(), C.blockCount());
874bba497fbSArtem Dergachev     State = State->BindExpr(CE, LC, V);
875bba497fbSArtem Dergachev     C.addTransition(State);
876bba497fbSArtem Dergachev     return true;
877bba497fbSArtem Dergachev   }
878bba497fbSArtem Dergachev   case NoEvalCall:
879bba497fbSArtem Dergachev     // Summary tells us to avoid performing eval::Call. The function is possibly
880bba497fbSArtem Dergachev     // evaluated by another checker, or evaluated conservatively.
881bba497fbSArtem Dergachev     return false;
882bba497fbSArtem Dergachev   }
883bba497fbSArtem Dergachev   llvm_unreachable("Unknown invalidation kind!");
884bba497fbSArtem Dergachev }
885bba497fbSArtem Dergachev 
88616506d78SGabor Marton bool StdLibraryFunctionsChecker::Signature::matches(
8878f961399SGabor Marton     const FunctionDecl *FD) const {
888a787a4edSGabor Marton   assert(!isInvalid());
889fe0972d3SGabor Marton   // Check the number of arguments.
8908f961399SGabor Marton   if (FD->param_size() != ArgTys.size())
891bba497fbSArtem Dergachev     return false;
892bba497fbSArtem Dergachev 
893fe0972d3SGabor Marton   // The "restrict" keyword is illegal in C++, however, many libc
894fe0972d3SGabor Marton   // implementations use the "__restrict" compiler intrinsic in functions
895fe0972d3SGabor Marton   // prototypes. The "__restrict" keyword qualifies a type as a restricted type
896fe0972d3SGabor Marton   // even in C++.
897fe0972d3SGabor Marton   // In case of any non-C99 languages, we don't want to match based on the
898fe0972d3SGabor Marton   // restrict qualifier because we cannot know if the given libc implementation
899fe0972d3SGabor Marton   // qualifies the paramter type or not.
900fe0972d3SGabor Marton   auto RemoveRestrict = [&FD](QualType T) {
901fe0972d3SGabor Marton     if (!FD->getASTContext().getLangOpts().C99)
902fe0972d3SGabor Marton       T.removeLocalRestrict();
903fe0972d3SGabor Marton     return T;
904fe0972d3SGabor Marton   };
905bba497fbSArtem Dergachev 
906fe0972d3SGabor Marton   // Check the return type.
907fe0972d3SGabor Marton   if (!isIrrelevant(RetTy)) {
908fe0972d3SGabor Marton     QualType FDRetTy = RemoveRestrict(FD->getReturnType().getCanonicalType());
909fe0972d3SGabor Marton     if (RetTy != FDRetTy)
910fe0972d3SGabor Marton       return false;
911fe0972d3SGabor Marton   }
912fe0972d3SGabor Marton 
913fe0972d3SGabor Marton   // Check the argument types.
914f5086b38SGabor Marton   for (size_t I = 0, E = ArgTys.size(); I != E; ++I) {
91516506d78SGabor Marton     QualType ArgTy = ArgTys[I];
91616506d78SGabor Marton     if (isIrrelevant(ArgTy))
917bba497fbSArtem Dergachev       continue;
918fe0972d3SGabor Marton     QualType FDArgTy =
919fe0972d3SGabor Marton         RemoveRestrict(FD->getParamDecl(I)->getType().getCanonicalType());
920fe0972d3SGabor Marton     if (ArgTy != FDArgTy)
921bba497fbSArtem Dergachev       return false;
922bba497fbSArtem Dergachev   }
923bba497fbSArtem Dergachev 
924bba497fbSArtem Dergachev   return true;
925bba497fbSArtem Dergachev }
926bba497fbSArtem Dergachev 
927f5086b38SGabor Marton Optional<StdLibraryFunctionsChecker::Summary>
928bba497fbSArtem Dergachev StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
929bba497fbSArtem Dergachev                                                 CheckerContext &C) const {
930bba497fbSArtem Dergachev   if (!FD)
931bba497fbSArtem Dergachev     return None;
932bba497fbSArtem Dergachev 
933536456a7SGabor Marton   initFunctionSummaries(C);
934bba497fbSArtem Dergachev 
93562e747f6SGabor Marton   auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl());
936bba497fbSArtem Dergachev   if (FSMI == FunctionSummaryMap.end())
937bba497fbSArtem Dergachev     return None;
93862e747f6SGabor Marton   return FSMI->second;
939bba497fbSArtem Dergachev }
940bba497fbSArtem Dergachev 
94194061df6SGabor Marton Optional<StdLibraryFunctionsChecker::Summary>
94294061df6SGabor Marton StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call,
94394061df6SGabor Marton                                                 CheckerContext &C) const {
94494061df6SGabor Marton   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
94594061df6SGabor Marton   if (!FD)
94694061df6SGabor Marton     return None;
9478f961399SGabor Marton   return findFunctionSummary(FD, C);
94894061df6SGabor Marton }
94994061df6SGabor Marton 
950a787a4edSGabor Marton void StdLibraryFunctionsChecker::initFunctionSummaries(
951a787a4edSGabor Marton     CheckerContext &C) const {
952c7635040SValeriy Savchenko   if (SummariesInitialized)
953a787a4edSGabor Marton     return;
954a787a4edSGabor Marton 
955a787a4edSGabor Marton   SValBuilder &SVB = C.getSValBuilder();
956a787a4edSGabor Marton   BasicValueFactory &BVF = SVB.getBasicValueFactory();
957a787a4edSGabor Marton   const ASTContext &ACtx = BVF.getContext();
958a787a4edSGabor Marton 
959a787a4edSGabor Marton   // Helper class to lookup a type by its name.
960a787a4edSGabor Marton   class LookupType {
961a787a4edSGabor Marton     const ASTContext &ACtx;
962a787a4edSGabor Marton 
963a787a4edSGabor Marton   public:
964a787a4edSGabor Marton     LookupType(const ASTContext &ACtx) : ACtx(ACtx) {}
965a787a4edSGabor Marton 
966a787a4edSGabor Marton     // Find the type. If not found then the optional is not set.
967a787a4edSGabor Marton     llvm::Optional<QualType> operator()(StringRef Name) {
968634258b8SGabor Marton       IdentifierInfo &II = ACtx.Idents.get(Name);
969634258b8SGabor Marton       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
9700cb7e7caSVassil Vassilev       if (LookupRes.empty())
971634258b8SGabor Marton         return None;
972634258b8SGabor Marton 
973634258b8SGabor Marton       // Prioritze typedef declarations.
974634258b8SGabor Marton       // This is needed in case of C struct typedefs. E.g.:
975634258b8SGabor Marton       //   typedef struct FILE FILE;
976a787a4edSGabor Marton       // In this case, we have a RecordDecl 'struct FILE' with the name 'FILE'
977a787a4edSGabor Marton       // and we have a TypedefDecl with the name 'FILE'.
978db4d5f70SGabor Marton       for (Decl *D : LookupRes)
979634258b8SGabor Marton         if (auto *TD = dyn_cast<TypedefNameDecl>(D))
980634258b8SGabor Marton           return ACtx.getTypeDeclType(TD).getCanonicalType();
981db4d5f70SGabor Marton 
982db4d5f70SGabor Marton       // Find the first TypeDecl.
983db4d5f70SGabor Marton       // There maybe cases when a function has the same name as a struct.
984db4d5f70SGabor Marton       // E.g. in POSIX: `struct stat` and the function `stat()`:
985db4d5f70SGabor Marton       //   int stat(const char *restrict path, struct stat *restrict buf);
986db4d5f70SGabor Marton       for (Decl *D : LookupRes)
987db4d5f70SGabor Marton         if (auto *TD = dyn_cast<TypeDecl>(D))
988db4d5f70SGabor Marton           return ACtx.getTypeDeclType(TD).getCanonicalType();
989db4d5f70SGabor Marton       return None;
990634258b8SGabor Marton     }
991a787a4edSGabor Marton   } lookupTy(ACtx);
992634258b8SGabor Marton 
993a787a4edSGabor Marton   // Below are auxiliary classes to handle optional types that we get as a
994a787a4edSGabor Marton   // result of the lookup.
995a787a4edSGabor Marton   class GetRestrictTy {
996a787a4edSGabor Marton     const ASTContext &ACtx;
997bba497fbSArtem Dergachev 
998a787a4edSGabor Marton   public:
999a787a4edSGabor Marton     GetRestrictTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1000a787a4edSGabor Marton     QualType operator()(QualType Ty) {
10013ff220deSGabor Marton       return ACtx.getLangOpts().C99 ? ACtx.getRestrictType(Ty) : Ty;
1002a787a4edSGabor Marton     }
1003a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1004a787a4edSGabor Marton       if (Ty)
1005a787a4edSGabor Marton         return operator()(*Ty);
1006a787a4edSGabor Marton       return None;
1007a787a4edSGabor Marton     }
1008a787a4edSGabor Marton   } getRestrictTy(ACtx);
1009a787a4edSGabor Marton   class GetPointerTy {
1010a787a4edSGabor Marton     const ASTContext &ACtx;
1011a787a4edSGabor Marton 
1012a787a4edSGabor Marton   public:
1013a787a4edSGabor Marton     GetPointerTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1014a787a4edSGabor Marton     QualType operator()(QualType Ty) { return ACtx.getPointerType(Ty); }
1015a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1016a787a4edSGabor Marton       if (Ty)
1017a787a4edSGabor Marton         return operator()(*Ty);
1018a787a4edSGabor Marton       return None;
1019a787a4edSGabor Marton     }
1020a787a4edSGabor Marton   } getPointerTy(ACtx);
1021a787a4edSGabor Marton   class {
1022a787a4edSGabor Marton   public:
1023a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1024a787a4edSGabor Marton       return Ty ? Optional<QualType>(Ty->withConst()) : None;
1025a787a4edSGabor Marton     }
1026a787a4edSGabor Marton     QualType operator()(QualType Ty) { return Ty.withConst(); }
1027a787a4edSGabor Marton   } getConstTy;
1028a787a4edSGabor Marton   class GetMaxValue {
1029a787a4edSGabor Marton     BasicValueFactory &BVF;
1030a787a4edSGabor Marton 
1031a787a4edSGabor Marton   public:
1032a787a4edSGabor Marton     GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {}
1033a787a4edSGabor Marton     Optional<RangeInt> operator()(QualType Ty) {
1034a787a4edSGabor Marton       return BVF.getMaxValue(Ty).getLimitedValue();
1035a787a4edSGabor Marton     }
1036a787a4edSGabor Marton     Optional<RangeInt> operator()(Optional<QualType> Ty) {
1037a787a4edSGabor Marton       if (Ty) {
1038a787a4edSGabor Marton         return operator()(*Ty);
1039a787a4edSGabor Marton       }
1040a787a4edSGabor Marton       return None;
1041a787a4edSGabor Marton     }
1042a787a4edSGabor Marton   } getMaxValue(BVF);
10433ff220deSGabor Marton 
1044bba497fbSArtem Dergachev   // These types are useful for writing specifications quickly,
1045bba497fbSArtem Dergachev   // New specifications should probably introduce more types.
104647fec16cSArtem Dergachev   // Some types are hard to obtain from the AST, eg. "ssize_t".
104747fec16cSArtem Dergachev   // In such cases it should be possible to provide multiple variants
104847fec16cSArtem Dergachev   // of function summary for common cases (eg. ssize_t could be int or long
104947fec16cSArtem Dergachev   // or long long, so three summary variants would be enough).
105047fec16cSArtem Dergachev   // Of course, function variants are also useful for C++ overloads.
1051db4d5f70SGabor Marton   const QualType VoidTy = ACtx.VoidTy;
1052a787a4edSGabor Marton   const QualType CharTy = ACtx.CharTy;
1053a787a4edSGabor Marton   const QualType WCharTy = ACtx.WCharTy;
1054536456a7SGabor Marton   const QualType IntTy = ACtx.IntTy;
1055db4d5f70SGabor Marton   const QualType UnsignedIntTy = ACtx.UnsignedIntTy;
1056536456a7SGabor Marton   const QualType LongTy = ACtx.LongTy;
1057536456a7SGabor Marton   const QualType SizeTy = ACtx.getSizeType();
1058db4d5f70SGabor Marton 
1059a787a4edSGabor Marton   const QualType VoidPtrTy = getPointerTy(VoidTy); // void *
1060a787a4edSGabor Marton   const QualType IntPtrTy = getPointerTy(IntTy);   // int *
1061db4d5f70SGabor Marton   const QualType UnsignedIntPtrTy =
1062a787a4edSGabor Marton       getPointerTy(UnsignedIntTy); // unsigned int *
10633ff220deSGabor Marton   const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy);
1064ededa65dSGabor Marton   const QualType ConstVoidPtrTy =
1065a787a4edSGabor Marton       getPointerTy(getConstTy(VoidTy));            // const void *
1066a787a4edSGabor Marton   const QualType CharPtrTy = getPointerTy(CharTy); // char *
10673ff220deSGabor Marton   const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy);
10688f961399SGabor Marton   const QualType ConstCharPtrTy =
1069a787a4edSGabor Marton       getPointerTy(getConstTy(CharTy)); // const char *
10703ff220deSGabor Marton   const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy);
1071a787a4edSGabor Marton   const QualType Wchar_tPtrTy = getPointerTy(WCharTy); // wchar_t *
1072db4d5f70SGabor Marton   const QualType ConstWchar_tPtrTy =
1073a787a4edSGabor Marton       getPointerTy(getConstTy(WCharTy)); // const wchar_t *
10743ff220deSGabor Marton   const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy);
1075d0128058SGabor Marton   const QualType SizePtrTy = getPointerTy(SizeTy);
1076d0128058SGabor Marton   const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy);
1077bba497fbSArtem Dergachev 
1078536456a7SGabor Marton   const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
1079db4d5f70SGabor Marton   const RangeInt UnsignedIntMax =
1080db4d5f70SGabor Marton       BVF.getMaxValue(UnsignedIntTy).getLimitedValue();
1081536456a7SGabor Marton   const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
1082db4d5f70SGabor Marton   const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue();
1083536456a7SGabor Marton 
10840eba5dc8SArtem Dergachev   // Set UCharRangeMax to min of int or uchar maximum value.
10850eba5dc8SArtem Dergachev   // The C standard states that the arguments of functions like isalpha must
10860eba5dc8SArtem Dergachev   // be representable as an unsigned char. Their type is 'int', so the max
10870eba5dc8SArtem Dergachev   // value of the argument should be min(UCharMax, IntMax). This just happen
10880eba5dc8SArtem Dergachev   // to be true for commonly used and well tested instruction set
10890eba5dc8SArtem Dergachev   // architectures, but not for others.
10900eba5dc8SArtem Dergachev   const RangeInt UCharRangeMax =
10910eba5dc8SArtem Dergachev       std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
1092536456a7SGabor Marton 
1093536456a7SGabor Marton   // The platform dependent value of EOF.
1094536456a7SGabor Marton   // Try our best to parse this from the Preprocessor, otherwise fallback to -1.
1095536456a7SGabor Marton   const auto EOFv = [&C]() -> RangeInt {
1096536456a7SGabor Marton     if (const llvm::Optional<int> OptInt =
1097536456a7SGabor Marton             tryExpandAsInteger("EOF", C.getPreprocessor()))
1098536456a7SGabor Marton       return *OptInt;
1099536456a7SGabor Marton     return -1;
1100536456a7SGabor Marton   }();
1101bba497fbSArtem Dergachev 
110262e747f6SGabor Marton   // Auxiliary class to aid adding summaries to the summary map.
110362e747f6SGabor Marton   struct AddToFunctionSummaryMap {
110462e747f6SGabor Marton     const ASTContext &ACtx;
110562e747f6SGabor Marton     FunctionSummaryMapType &Map;
1106ff4492c8SGabor Marton     bool DisplayLoadedSummaries;
1107ff4492c8SGabor Marton     AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM,
1108ff4492c8SGabor Marton                             bool DisplayLoadedSummaries)
1109ff4492c8SGabor Marton         : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) {
1110ff4492c8SGabor Marton     }
1111ff4492c8SGabor Marton 
111262e747f6SGabor Marton     // Add a summary to a FunctionDecl found by lookup. The lookup is performed
111362e747f6SGabor Marton     // by the given Name, and in the global scope. The summary will be attached
111462e747f6SGabor Marton     // to the found FunctionDecl only if the signatures match.
11153ff220deSGabor Marton     //
11163ff220deSGabor Marton     // Returns true if the summary has been added, false otherwise.
111711d2e63aSGabor Marton     bool operator()(StringRef Name, Signature Sign, Summary Sum) {
111811d2e63aSGabor Marton       if (Sign.isInvalid())
1119a787a4edSGabor Marton         return false;
112062e747f6SGabor Marton       IdentifierInfo &II = ACtx.Idents.get(Name);
112162e747f6SGabor Marton       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
11220cb7e7caSVassil Vassilev       if (LookupRes.empty())
11233ff220deSGabor Marton         return false;
112462e747f6SGabor Marton       for (Decl *D : LookupRes) {
112562e747f6SGabor Marton         if (auto *FD = dyn_cast<FunctionDecl>(D)) {
112611d2e63aSGabor Marton           if (Sum.matchesAndSet(Sign, FD)) {
112711d2e63aSGabor Marton             auto Res = Map.insert({FD->getCanonicalDecl(), Sum});
112862e747f6SGabor Marton             assert(Res.second && "Function already has a summary set!");
112962e747f6SGabor Marton             (void)Res;
1130ff4492c8SGabor Marton             if (DisplayLoadedSummaries) {
1131ff4492c8SGabor Marton               llvm::errs() << "Loaded summary for: ";
1132ff4492c8SGabor Marton               FD->print(llvm::errs());
1133ff4492c8SGabor Marton               llvm::errs() << "\n";
1134ff4492c8SGabor Marton             }
11353ff220deSGabor Marton             return true;
113662e747f6SGabor Marton           }
113762e747f6SGabor Marton         }
113862e747f6SGabor Marton       }
11393ff220deSGabor Marton       return false;
11403ff220deSGabor Marton     }
1141fe0972d3SGabor Marton     // Add the same summary for different names with the Signature explicitly
1142fe0972d3SGabor Marton     // given.
1143fe0972d3SGabor Marton     void operator()(std::vector<StringRef> Names, Signature Sign, Summary Sum) {
1144fe0972d3SGabor Marton       for (StringRef Name : Names)
1145fe0972d3SGabor Marton         operator()(Name, Sign, Sum);
1146fe0972d3SGabor Marton     }
1147ff4492c8SGabor Marton   } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries);
114862e747f6SGabor Marton 
1149c6b8484eSGabor Marton   // Below are helpers functions to create the summaries.
1150c6b8484eSGabor Marton   auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind,
1151c6b8484eSGabor Marton                               IntRangeVector Ranges) {
1152c6b8484eSGabor Marton     return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges);
1153f5086b38SGabor Marton   };
115441928c97SGabor Marton   auto BufferSize = [](auto... Args) {
115541928c97SGabor Marton     return std::make_shared<BufferSizeConstraint>(Args...);
1156bd03ef19SGabor Marton   };
1157c6b8484eSGabor Marton   struct {
1158c6b8484eSGabor Marton     auto operator()(RangeKind Kind, IntRangeVector Ranges) {
1159c6b8484eSGabor Marton       return std::make_shared<RangeConstraint>(Ret, Kind, Ranges);
1160c6b8484eSGabor Marton     }
1161c6b8484eSGabor Marton     auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) {
1162c6b8484eSGabor Marton       return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN);
1163c6b8484eSGabor Marton     }
1164c6b8484eSGabor Marton   } ReturnValueCondition;
1165a787a4edSGabor Marton   struct {
1166a787a4edSGabor Marton     auto operator()(RangeInt b, RangeInt e) {
1167f5086b38SGabor Marton       return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}};
1168a787a4edSGabor Marton     }
1169a787a4edSGabor Marton     auto operator()(RangeInt b, Optional<RangeInt> e) {
1170a787a4edSGabor Marton       if (e)
1171a787a4edSGabor Marton         return IntRangeVector{std::pair<RangeInt, RangeInt>{b, *e}};
1172a787a4edSGabor Marton       return IntRangeVector{};
1173a787a4edSGabor Marton     }
1174d63a945aSGabor Marton     auto operator()(std::pair<RangeInt, RangeInt> i0,
1175d63a945aSGabor Marton                     std::pair<RangeInt, Optional<RangeInt>> i1) {
1176d63a945aSGabor Marton       if (i1.second)
1177d63a945aSGabor Marton         return IntRangeVector{i0, {i1.first, *(i1.second)}};
1178d63a945aSGabor Marton       return IntRangeVector{i0};
1179d63a945aSGabor Marton     }
1180a787a4edSGabor Marton   } Range;
1181f5086b38SGabor Marton   auto SingleValue = [](RangeInt v) {
1182f5086b38SGabor Marton     return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}};
1183f5086b38SGabor Marton   };
1184c6b8484eSGabor Marton   auto LessThanOrEq = BO_LE;
1185ededa65dSGabor Marton   auto NotNull = [&](ArgNo ArgN) {
1186ededa65dSGabor Marton     return std::make_shared<NotNullConstraint>(ArgN);
1187ededa65dSGabor Marton   };
1188f5086b38SGabor Marton 
1189a787a4edSGabor Marton   Optional<QualType> FileTy = lookupTy("FILE");
1190a787a4edSGabor Marton   Optional<QualType> FilePtrTy = getPointerTy(FileTy);
1191a787a4edSGabor Marton   Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy);
1192634258b8SGabor Marton 
1193a787a4edSGabor Marton   // We are finally ready to define specifications for all supported functions.
1194a787a4edSGabor Marton   //
1195a787a4edSGabor Marton   // Argument ranges should always cover all variants. If return value
1196a787a4edSGabor Marton   // is completely unknown, omit it from the respective range set.
1197a787a4edSGabor Marton   //
1198a787a4edSGabor Marton   // Every item in the list of range sets represents a particular
1199a787a4edSGabor Marton   // execution path the analyzer would need to explore once
1200a787a4edSGabor Marton   // the call is modeled - a new program state is constructed
1201a787a4edSGabor Marton   // for every range set, and each range line in the range set
1202a787a4edSGabor Marton   // corresponds to a specific constraint within this state.
1203a787a4edSGabor Marton 
1204bba497fbSArtem Dergachev   // The isascii() family of functions.
120594061df6SGabor Marton   // The behavior is undefined if the value of the argument is not
120694061df6SGabor Marton   // representable as unsigned char or is not equal to EOF. See e.g. C99
120794061df6SGabor Marton   // 7.4.1.2 The isalpha function (p: 181-182).
120862e747f6SGabor Marton   addToFunctionSummaryMap(
120911d2e63aSGabor Marton       "isalnum", Signature(ArgTypes{IntTy}, RetType{IntTy}),
121011d2e63aSGabor Marton       Summary(EvalCallAsPure)
1211f5086b38SGabor Marton           // Boils down to isupper() or islower() or isdigit().
121262e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange,
1213f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}),
1214f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1215f5086b38SGabor Marton           // The locale-specific range.
1216bba497fbSArtem Dergachev           // No post-condition. We are completely unaware of
1217bba497fbSArtem Dergachev           // locale-specific return values.
121862e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
121962e747f6SGabor Marton           .Case(
122062e747f6SGabor Marton               {ArgumentCondition(
122162e747f6SGabor Marton                    0U, OutOfRange,
122262e747f6SGabor Marton                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
122394061df6SGabor Marton                ReturnValueCondition(WithinRange, SingleValue(0))})
122494061df6SGabor Marton           .ArgConstraint(ArgumentCondition(
122562e747f6SGabor Marton               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
122662e747f6SGabor Marton   addToFunctionSummaryMap(
122711d2e63aSGabor Marton       "isalpha", Signature(ArgTypes{IntTy}, RetType{IntTy}),
122811d2e63aSGabor Marton       Summary(EvalCallAsPure)
122962e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}),
1230f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1231f5086b38SGabor Marton           // The locale-specific range.
123262e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1233536456a7SGabor Marton           .Case({ArgumentCondition(
1234536456a7SGabor Marton                      0U, OutOfRange,
12350eba5dc8SArtem Dergachev                      {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
123662e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
123762e747f6SGabor Marton   addToFunctionSummaryMap(
123811d2e63aSGabor Marton       "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
123911d2e63aSGabor Marton       Summary(EvalCallAsPure)
1240f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1241f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1242f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)),
124362e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
124462e747f6SGabor Marton   addToFunctionSummaryMap(
124511d2e63aSGabor Marton       "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}),
124611d2e63aSGabor Marton       Summary(EvalCallAsPure)
124762e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}),
1248f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
124962e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}),
125062e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
125162e747f6SGabor Marton   addToFunctionSummaryMap(
125211d2e63aSGabor Marton       "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}),
125311d2e63aSGabor Marton       Summary(EvalCallAsPure)
125462e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}),
1255f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
125662e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}),
125762e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
125862e747f6SGabor Marton   addToFunctionSummaryMap(
125911d2e63aSGabor Marton       "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
126011d2e63aSGabor Marton       Summary(EvalCallAsPure)
1261f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')),
1262f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1263f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')),
126462e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
126562e747f6SGabor Marton   addToFunctionSummaryMap(
126611d2e63aSGabor Marton       "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}),
126711d2e63aSGabor Marton       Summary(EvalCallAsPure)
1268f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)),
1269f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1270f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)),
127162e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
127262e747f6SGabor Marton   addToFunctionSummaryMap(
127311d2e63aSGabor Marton       "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
127411d2e63aSGabor Marton       Summary(EvalCallAsPure)
1275f5086b38SGabor Marton           // Is certainly lowercase.
1276f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')),
1277f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1278f5086b38SGabor Marton           // Is ascii but not lowercase.
1279f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1280f5086b38SGabor Marton                  ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
1281f5086b38SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))})
1282f5086b38SGabor Marton           // The locale-specific range.
128362e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1284f5086b38SGabor Marton           // Is not an unsigned char.
128562e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)),
128662e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
128762e747f6SGabor Marton   addToFunctionSummaryMap(
128811d2e63aSGabor Marton       "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
128911d2e63aSGabor Marton       Summary(EvalCallAsPure)
1290f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
1291f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1292f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
129362e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
129462e747f6SGabor Marton   addToFunctionSummaryMap(
129511d2e63aSGabor Marton       "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}),
129611d2e63aSGabor Marton       Summary(EvalCallAsPure)
1297f5086b38SGabor Marton           .Case({ArgumentCondition(
1298f5086b38SGabor Marton                      0U, WithinRange,
1299f5086b38SGabor Marton                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1300f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1301f5086b38SGabor Marton           .Case({ArgumentCondition(
1302f5086b38SGabor Marton                      0U, OutOfRange,
1303f5086b38SGabor Marton                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
130462e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
130562e747f6SGabor Marton   addToFunctionSummaryMap(
130611d2e63aSGabor Marton       "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}),
130711d2e63aSGabor Marton       Summary(EvalCallAsPure)
1308f5086b38SGabor Marton           // Space, '\f', '\n', '\r', '\t', '\v'.
130962e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}),
1310f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1311f5086b38SGabor Marton           // The locale-specific range.
131262e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
131362e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
13140eba5dc8SArtem Dergachev                                    {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
131562e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
131662e747f6SGabor Marton   addToFunctionSummaryMap(
131711d2e63aSGabor Marton       "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
131811d2e63aSGabor Marton       Summary(EvalCallAsPure)
1319f5086b38SGabor Marton           // Is certainly uppercase.
1320f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
1321f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
1322f5086b38SGabor Marton           // The locale-specific range.
132362e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1324f5086b38SGabor Marton           // Other.
1325f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
13260eba5dc8SArtem Dergachev                                    {{'A', 'Z'}, {128, UCharRangeMax}}),
132762e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
132862e747f6SGabor Marton   addToFunctionSummaryMap(
132911d2e63aSGabor Marton       "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
133011d2e63aSGabor Marton       Summary(EvalCallAsPure)
133162e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange,
1332f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1333f5086b38SGabor Marton                  ReturnValueCondition(OutOfRange, SingleValue(0))})
133462e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
1335f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
133662e747f6SGabor Marton                  ReturnValueCondition(WithinRange, SingleValue(0))}));
133725bbe234SZurab Tsinadze   addToFunctionSummaryMap(
133811d2e63aSGabor Marton       "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
133911d2e63aSGabor Marton       Summary(EvalCallAsPure)
134025bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
134125bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
134225bbe234SZurab Tsinadze   addToFunctionSummaryMap(
134311d2e63aSGabor Marton       "tolower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
134411d2e63aSGabor Marton       Summary(EvalCallAsPure)
134525bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
134625bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
134725bbe234SZurab Tsinadze   addToFunctionSummaryMap(
134811d2e63aSGabor Marton       "toascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
134911d2e63aSGabor Marton       Summary(EvalCallAsPure)
135025bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
135125bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1352bba497fbSArtem Dergachev 
1353bba497fbSArtem Dergachev   // The getc() family of functions that returns either a char or an EOF.
1354a012bc4cSGabor Marton   addToFunctionSummaryMap(
1355a012bc4cSGabor Marton       {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1356a012bc4cSGabor Marton       Summary(NoEvalCall)
1357a012bc4cSGabor Marton           .Case({ReturnValueCondition(WithinRange,
1358a012bc4cSGabor Marton                                       {{EOFv, EOFv}, {0, UCharRangeMax}})}));
135962e747f6SGabor Marton   addToFunctionSummaryMap(
136011d2e63aSGabor Marton       "getchar", Signature(ArgTypes{}, RetType{IntTy}),
136111d2e63aSGabor Marton       Summary(NoEvalCall)
136211d2e63aSGabor Marton           .Case({ReturnValueCondition(WithinRange,
136311d2e63aSGabor Marton                                       {{EOFv, EOFv}, {0, UCharRangeMax}})}));
1364bba497fbSArtem Dergachev 
1365bba497fbSArtem Dergachev   // read()-like functions that never return more than buffer size.
1366a012bc4cSGabor Marton   auto FreadSummary =
1367a012bc4cSGabor Marton       Summary(NoEvalCall)
1368b40b3196SGabor Marton           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1369b40b3196SGabor Marton                  ReturnValueCondition(WithinRange, Range(0, SizeMax))})
1370a012bc4cSGabor Marton           .ArgConstraint(NotNull(ArgNo(0)))
1371a012bc4cSGabor Marton           .ArgConstraint(NotNull(ArgNo(3)))
1372a012bc4cSGabor Marton           .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
1373a012bc4cSGabor Marton                                     /*BufSizeMultiplier=*/ArgNo(2)));
1374a012bc4cSGabor Marton 
1375a012bc4cSGabor Marton   // size_t fread(void *restrict ptr, size_t size, size_t nitems,
1376a012bc4cSGabor Marton   //              FILE *restrict stream);
1377a012bc4cSGabor Marton   addToFunctionSummaryMap(
1378a012bc4cSGabor Marton       "fread",
1379a012bc4cSGabor Marton       Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
1380a012bc4cSGabor Marton                 RetType{SizeTy}),
1381a012bc4cSGabor Marton       FreadSummary);
1382a012bc4cSGabor Marton   // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
1383a012bc4cSGabor Marton   //               FILE *restrict stream);
1384a012bc4cSGabor Marton   addToFunctionSummaryMap("fwrite",
1385a012bc4cSGabor Marton                           Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy,
1386a012bc4cSGabor Marton                                              SizeTy, FilePtrRestrictTy},
1387a012bc4cSGabor Marton                                     RetType{SizeTy}),
1388a012bc4cSGabor Marton                           FreadSummary);
1389634258b8SGabor Marton 
1390d63a945aSGabor Marton   Optional<QualType> Ssize_tTy = lookupTy("ssize_t");
1391d63a945aSGabor Marton   Optional<RangeInt> Ssize_tMax = getMaxValue(Ssize_tTy);
1392d63a945aSGabor Marton 
1393d63a945aSGabor Marton   auto ReadSummary =
1394d63a945aSGabor Marton       Summary(NoEvalCall)
1395d63a945aSGabor Marton           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1396d63a945aSGabor Marton                  ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))});
1397d63a945aSGabor Marton 
1398634258b8SGabor Marton   // FIXME these are actually defined by POSIX and not by the C standard, we
1399634258b8SGabor Marton   // should handle them together with the rest of the POSIX functions.
1400d63a945aSGabor Marton   // ssize_t read(int fildes, void *buf, size_t nbyte);
1401d63a945aSGabor Marton   addToFunctionSummaryMap(
1402d63a945aSGabor Marton       "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1403d63a945aSGabor Marton       ReadSummary);
1404d63a945aSGabor Marton   // ssize_t write(int fildes, const void *buf, size_t nbyte);
1405d63a945aSGabor Marton   addToFunctionSummaryMap(
1406d63a945aSGabor Marton       "write",
1407d63a945aSGabor Marton       Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1408d63a945aSGabor Marton       ReadSummary);
1409d63a945aSGabor Marton 
1410d63a945aSGabor Marton   auto GetLineSummary =
1411d63a945aSGabor Marton       Summary(NoEvalCall)
1412d63a945aSGabor Marton           .Case({ReturnValueCondition(WithinRange,
1413d63a945aSGabor Marton                                       Range({-1, -1}, {1, Ssize_tMax}))});
1414d63a945aSGabor Marton 
1415d63a945aSGabor Marton   QualType CharPtrPtrRestrictTy = getRestrictTy(getPointerTy(CharPtrTy));
1416634258b8SGabor Marton 
1417bba497fbSArtem Dergachev   // getline()-like functions either fail or read at least the delimiter.
1418634258b8SGabor Marton   // FIXME these are actually defined by POSIX and not by the C standard, we
1419634258b8SGabor Marton   // should handle them together with the rest of the POSIX functions.
1420d63a945aSGabor Marton   // ssize_t getline(char **restrict lineptr, size_t *restrict n,
1421d63a945aSGabor Marton   //                 FILE *restrict stream);
1422d63a945aSGabor Marton   addToFunctionSummaryMap(
1423d63a945aSGabor Marton       "getline",
1424d63a945aSGabor Marton       Signature(
1425d63a945aSGabor Marton           ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, FilePtrRestrictTy},
1426d63a945aSGabor Marton           RetType{Ssize_tTy}),
1427d63a945aSGabor Marton       GetLineSummary);
1428d63a945aSGabor Marton   // ssize_t getdelim(char **restrict lineptr, size_t *restrict n,
1429d63a945aSGabor Marton   //                  int delimiter, FILE *restrict stream);
1430d63a945aSGabor Marton   addToFunctionSummaryMap(
1431d63a945aSGabor Marton       "getdelim",
1432d63a945aSGabor Marton       Signature(ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, IntTy,
1433d63a945aSGabor Marton                          FilePtrRestrictTy},
1434d63a945aSGabor Marton                 RetType{Ssize_tTy}),
1435d63a945aSGabor Marton       GetLineSummary);
14361525232eSGabor Marton 
1437*edde4efcSBalazs Benics   {
1438*edde4efcSBalazs Benics     Summary GetenvSummary = Summary(NoEvalCall)
1439*edde4efcSBalazs Benics                                 .ArgConstraint(NotNull(ArgNo(0)))
1440*edde4efcSBalazs Benics                                 .Case({NotNull(Ret)});
1441*edde4efcSBalazs Benics     // In untrusted environments the envvar might not exist.
1442*edde4efcSBalazs Benics     if (!ShouldAssumeControlledEnvironment)
1443*edde4efcSBalazs Benics       GetenvSummary.Case({NotNull(Ret)->negate()});
1444*edde4efcSBalazs Benics 
14457fc15030SBalazs Benics     // char *getenv(const char *name);
14467fc15030SBalazs Benics     addToFunctionSummaryMap(
14477fc15030SBalazs Benics         "getenv", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1448*edde4efcSBalazs Benics         std::move(GetenvSummary));
1449*edde4efcSBalazs Benics   }
14507fc15030SBalazs Benics 
1451db4d5f70SGabor Marton   if (ModelPOSIX) {
1452db4d5f70SGabor Marton 
1453db4d5f70SGabor Marton     // long a64l(const char *str64);
1454db4d5f70SGabor Marton     addToFunctionSummaryMap(
145511d2e63aSGabor Marton         "a64l", Signature(ArgTypes{ConstCharPtrTy}, RetType{LongTy}),
145611d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1457db4d5f70SGabor Marton 
1458db4d5f70SGabor Marton     // char *l64a(long value);
145911d2e63aSGabor Marton     addToFunctionSummaryMap("l64a",
146011d2e63aSGabor Marton                             Signature(ArgTypes{LongTy}, RetType{CharPtrTy}),
146111d2e63aSGabor Marton                             Summary(NoEvalCall)
146211d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
146311d2e63aSGabor Marton                                     0, WithinRange, Range(0, LongMax))));
1464db4d5f70SGabor Marton 
1465febe7503SGabor Marton     const auto ReturnsZeroOrMinusOne =
1466febe7503SGabor Marton         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
1467febe7503SGabor Marton     const auto ReturnsFileDescriptor =
1468febe7503SGabor Marton         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
1469febe7503SGabor Marton 
1470db4d5f70SGabor Marton     // int access(const char *pathname, int amode);
147111d2e63aSGabor Marton     addToFunctionSummaryMap(
147211d2e63aSGabor Marton         "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
1473febe7503SGabor Marton         Summary(NoEvalCall)
1474febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1475febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1476db4d5f70SGabor Marton 
1477db4d5f70SGabor Marton     // int faccessat(int dirfd, const char *pathname, int mode, int flags);
1478db4d5f70SGabor Marton     addToFunctionSummaryMap(
147911d2e63aSGabor Marton         "faccessat",
148011d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
148111d2e63aSGabor Marton                   RetType{IntTy}),
1482febe7503SGabor Marton         Summary(NoEvalCall)
1483febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1484febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1485db4d5f70SGabor Marton 
1486db4d5f70SGabor Marton     // int dup(int fildes);
148711d2e63aSGabor Marton     addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
148811d2e63aSGabor Marton                             Summary(NoEvalCall)
1489febe7503SGabor Marton                                 .Case(ReturnsFileDescriptor)
149011d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
149111d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1492db4d5f70SGabor Marton 
1493db4d5f70SGabor Marton     // int dup2(int fildes1, int filedes2);
1494db4d5f70SGabor Marton     addToFunctionSummaryMap(
149511d2e63aSGabor Marton         "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
149611d2e63aSGabor Marton         Summary(NoEvalCall)
1497febe7503SGabor Marton             .Case(ReturnsFileDescriptor)
1498db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1499db4d5f70SGabor Marton             .ArgConstraint(
1500db4d5f70SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, IntMax))));
1501db4d5f70SGabor Marton 
1502db4d5f70SGabor Marton     // int fdatasync(int fildes);
150311d2e63aSGabor Marton     addToFunctionSummaryMap("fdatasync",
150411d2e63aSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
150511d2e63aSGabor Marton                             Summary(NoEvalCall)
1506febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
150711d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
150811d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1509db4d5f70SGabor Marton 
1510db4d5f70SGabor Marton     // int fnmatch(const char *pattern, const char *string, int flags);
1511db4d5f70SGabor Marton     addToFunctionSummaryMap(
151211d2e63aSGabor Marton         "fnmatch",
151311d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy},
151411d2e63aSGabor Marton                   RetType{IntTy}),
151511d2e63aSGabor Marton         Summary(EvalCallAsPure)
1516db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1517db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1518db4d5f70SGabor Marton 
1519db4d5f70SGabor Marton     // int fsync(int fildes);
152011d2e63aSGabor Marton     addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}),
152111d2e63aSGabor Marton                             Summary(NoEvalCall)
1522febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
152311d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
152411d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1525db4d5f70SGabor Marton 
1526a787a4edSGabor Marton     Optional<QualType> Off_tTy = lookupTy("off_t");
1527db4d5f70SGabor Marton 
1528db4d5f70SGabor Marton     // int truncate(const char *path, off_t length);
1529a787a4edSGabor Marton     addToFunctionSummaryMap(
1530a787a4edSGabor Marton         "truncate",
153111d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
1532febe7503SGabor Marton         Summary(NoEvalCall)
1533febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1534febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1535db4d5f70SGabor Marton 
1536db4d5f70SGabor Marton     // int symlink(const char *oldpath, const char *newpath);
153711d2e63aSGabor Marton     addToFunctionSummaryMap(
153811d2e63aSGabor Marton         "symlink",
153911d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
154011d2e63aSGabor Marton         Summary(NoEvalCall)
1541febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1542db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1543db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1544db4d5f70SGabor Marton 
1545db4d5f70SGabor Marton     // int symlinkat(const char *oldpath, int newdirfd, const char *newpath);
1546db4d5f70SGabor Marton     addToFunctionSummaryMap(
1547db4d5f70SGabor Marton         "symlinkat",
154811d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
154911d2e63aSGabor Marton                   RetType{IntTy}),
155011d2e63aSGabor Marton         Summary(NoEvalCall)
1551febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1552db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1553db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
1554db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
1555db4d5f70SGabor Marton 
1556db4d5f70SGabor Marton     // int lockf(int fd, int cmd, off_t len);
1557db4d5f70SGabor Marton     addToFunctionSummaryMap(
155811d2e63aSGabor Marton         "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}),
155911d2e63aSGabor Marton         Summary(NoEvalCall)
1560febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1561db4d5f70SGabor Marton             .ArgConstraint(
1562db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1563db4d5f70SGabor Marton 
1564a787a4edSGabor Marton     Optional<QualType> Mode_tTy = lookupTy("mode_t");
1565db4d5f70SGabor Marton 
1566db4d5f70SGabor Marton     // int creat(const char *pathname, mode_t mode);
156711d2e63aSGabor Marton     addToFunctionSummaryMap(
156811d2e63aSGabor Marton         "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1569febe7503SGabor Marton         Summary(NoEvalCall)
1570febe7503SGabor Marton             .Case(ReturnsFileDescriptor)
1571febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1572db4d5f70SGabor Marton 
1573db4d5f70SGabor Marton     // unsigned int sleep(unsigned int seconds);
1574db4d5f70SGabor Marton     addToFunctionSummaryMap(
157511d2e63aSGabor Marton         "sleep", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
157611d2e63aSGabor Marton         Summary(NoEvalCall)
1577db4d5f70SGabor Marton             .ArgConstraint(
1578db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1579db4d5f70SGabor Marton 
1580a787a4edSGabor Marton     Optional<QualType> DirTy = lookupTy("DIR");
1581a787a4edSGabor Marton     Optional<QualType> DirPtrTy = getPointerTy(DirTy);
1582db4d5f70SGabor Marton 
1583db4d5f70SGabor Marton     // int dirfd(DIR *dirp);
1584febe7503SGabor Marton     addToFunctionSummaryMap("dirfd",
1585febe7503SGabor Marton                             Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1586febe7503SGabor Marton                             Summary(NoEvalCall)
1587febe7503SGabor Marton                                 .Case(ReturnsFileDescriptor)
1588febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1589db4d5f70SGabor Marton 
1590db4d5f70SGabor Marton     // unsigned int alarm(unsigned int seconds);
1591db4d5f70SGabor Marton     addToFunctionSummaryMap(
159211d2e63aSGabor Marton         "alarm", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
159311d2e63aSGabor Marton         Summary(NoEvalCall)
1594db4d5f70SGabor Marton             .ArgConstraint(
1595db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1596db4d5f70SGabor Marton 
1597db4d5f70SGabor Marton     // int closedir(DIR *dir);
1598febe7503SGabor Marton     addToFunctionSummaryMap("closedir",
1599febe7503SGabor Marton                             Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1600febe7503SGabor Marton                             Summary(NoEvalCall)
1601febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
1602febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1603db4d5f70SGabor Marton 
1604db4d5f70SGabor Marton     // char *strdup(const char *s);
160511d2e63aSGabor Marton     addToFunctionSummaryMap(
160611d2e63aSGabor Marton         "strdup", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
160711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1608db4d5f70SGabor Marton 
1609db4d5f70SGabor Marton     // char *strndup(const char *s, size_t n);
1610db4d5f70SGabor Marton     addToFunctionSummaryMap(
161111d2e63aSGabor Marton         "strndup",
161211d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}),
161311d2e63aSGabor Marton         Summary(NoEvalCall)
1614db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
161511d2e63aSGabor Marton             .ArgConstraint(
161611d2e63aSGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1617db4d5f70SGabor Marton 
1618db4d5f70SGabor Marton     // wchar_t *wcsdup(const wchar_t *s);
161911d2e63aSGabor Marton     addToFunctionSummaryMap(
162011d2e63aSGabor Marton         "wcsdup", Signature(ArgTypes{ConstWchar_tPtrTy}, RetType{Wchar_tPtrTy}),
162111d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1622db4d5f70SGabor Marton 
1623db4d5f70SGabor Marton     // int mkstemp(char *template);
1624febe7503SGabor Marton     addToFunctionSummaryMap("mkstemp",
1625febe7503SGabor Marton                             Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
1626febe7503SGabor Marton                             Summary(NoEvalCall)
1627febe7503SGabor Marton                                 .Case(ReturnsFileDescriptor)
1628febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1629db4d5f70SGabor Marton 
1630db4d5f70SGabor Marton     // char *mkdtemp(char *template);
1631db4d5f70SGabor Marton     addToFunctionSummaryMap(
163211d2e63aSGabor Marton         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
163311d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1634db4d5f70SGabor Marton 
1635db4d5f70SGabor Marton     // char *getcwd(char *buf, size_t size);
1636db4d5f70SGabor Marton     addToFunctionSummaryMap(
163711d2e63aSGabor Marton         "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
163811d2e63aSGabor Marton         Summary(NoEvalCall)
1639db4d5f70SGabor Marton             .ArgConstraint(
1640db4d5f70SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1641db4d5f70SGabor Marton 
1642db4d5f70SGabor Marton     // int mkdir(const char *pathname, mode_t mode);
164311d2e63aSGabor Marton     addToFunctionSummaryMap(
164411d2e63aSGabor Marton         "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1645febe7503SGabor Marton         Summary(NoEvalCall)
1646febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1647febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1648db4d5f70SGabor Marton 
1649db4d5f70SGabor Marton     // int mkdirat(int dirfd, const char *pathname, mode_t mode);
165011d2e63aSGabor Marton     addToFunctionSummaryMap(
165111d2e63aSGabor Marton         "mkdirat",
165211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1653febe7503SGabor Marton         Summary(NoEvalCall)
1654febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1655febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1656db4d5f70SGabor Marton 
1657a787a4edSGabor Marton     Optional<QualType> Dev_tTy = lookupTy("dev_t");
1658db4d5f70SGabor Marton 
1659db4d5f70SGabor Marton     // int mknod(const char *pathname, mode_t mode, dev_t dev);
166011d2e63aSGabor Marton     addToFunctionSummaryMap(
166111d2e63aSGabor Marton         "mknod",
166211d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}),
1663febe7503SGabor Marton         Summary(NoEvalCall)
1664febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1665febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1666db4d5f70SGabor Marton 
1667db4d5f70SGabor Marton     // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
1668a787a4edSGabor Marton     addToFunctionSummaryMap(
166911d2e63aSGabor Marton         "mknodat",
167011d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy},
167111d2e63aSGabor Marton                   RetType{IntTy}),
1672febe7503SGabor Marton         Summary(NoEvalCall)
1673febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1674febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1675db4d5f70SGabor Marton 
1676db4d5f70SGabor Marton     // int chmod(const char *path, mode_t mode);
167711d2e63aSGabor Marton     addToFunctionSummaryMap(
167811d2e63aSGabor Marton         "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1679febe7503SGabor Marton         Summary(NoEvalCall)
1680febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1681febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1682db4d5f70SGabor Marton 
1683db4d5f70SGabor Marton     // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
1684db4d5f70SGabor Marton     addToFunctionSummaryMap(
1685a787a4edSGabor Marton         "fchmodat",
168611d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy},
168711d2e63aSGabor Marton                   RetType{IntTy}),
168811d2e63aSGabor Marton         Summary(NoEvalCall)
1689febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1690a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1691db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1692db4d5f70SGabor Marton 
1693db4d5f70SGabor Marton     // int fchmod(int fildes, mode_t mode);
1694db4d5f70SGabor Marton     addToFunctionSummaryMap(
169511d2e63aSGabor Marton         "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}),
169611d2e63aSGabor Marton         Summary(NoEvalCall)
1697febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1698db4d5f70SGabor Marton             .ArgConstraint(
1699db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1700db4d5f70SGabor Marton 
1701a787a4edSGabor Marton     Optional<QualType> Uid_tTy = lookupTy("uid_t");
1702a787a4edSGabor Marton     Optional<QualType> Gid_tTy = lookupTy("gid_t");
1703db4d5f70SGabor Marton 
1704db4d5f70SGabor Marton     // int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group,
1705db4d5f70SGabor Marton     //              int flags);
1706db4d5f70SGabor Marton     addToFunctionSummaryMap(
1707db4d5f70SGabor Marton         "fchownat",
170811d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy},
170911d2e63aSGabor Marton                   RetType{IntTy}),
171011d2e63aSGabor Marton         Summary(NoEvalCall)
1711febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1712a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1713db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1714db4d5f70SGabor Marton 
1715db4d5f70SGabor Marton     // int chown(const char *path, uid_t owner, gid_t group);
171611d2e63aSGabor Marton     addToFunctionSummaryMap(
171711d2e63aSGabor Marton         "chown",
171811d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1719febe7503SGabor Marton         Summary(NoEvalCall)
1720febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1721febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1722db4d5f70SGabor Marton 
1723db4d5f70SGabor Marton     // int lchown(const char *path, uid_t owner, gid_t group);
172411d2e63aSGabor Marton     addToFunctionSummaryMap(
172511d2e63aSGabor Marton         "lchown",
172611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1727febe7503SGabor Marton         Summary(NoEvalCall)
1728febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1729febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1730db4d5f70SGabor Marton 
1731db4d5f70SGabor Marton     // int fchown(int fildes, uid_t owner, gid_t group);
1732db4d5f70SGabor Marton     addToFunctionSummaryMap(
173311d2e63aSGabor Marton         "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
173411d2e63aSGabor Marton         Summary(NoEvalCall)
1735febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1736a787a4edSGabor Marton             .ArgConstraint(
1737a787a4edSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1738db4d5f70SGabor Marton 
1739db4d5f70SGabor Marton     // int rmdir(const char *pathname);
1740febe7503SGabor Marton     addToFunctionSummaryMap("rmdir",
1741febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1742febe7503SGabor Marton                             Summary(NoEvalCall)
1743febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
1744febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1745db4d5f70SGabor Marton 
1746db4d5f70SGabor Marton     // int chdir(const char *path);
1747febe7503SGabor Marton     addToFunctionSummaryMap("chdir",
1748febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1749febe7503SGabor Marton                             Summary(NoEvalCall)
1750febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
1751febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1752db4d5f70SGabor Marton 
1753db4d5f70SGabor Marton     // int link(const char *oldpath, const char *newpath);
175411d2e63aSGabor Marton     addToFunctionSummaryMap(
175511d2e63aSGabor Marton         "link",
175611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
175711d2e63aSGabor Marton         Summary(NoEvalCall)
1758febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1759db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1760db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1761db4d5f70SGabor Marton 
1762db4d5f70SGabor Marton     // int linkat(int fd1, const char *path1, int fd2, const char *path2,
1763db4d5f70SGabor Marton     //            int flag);
1764db4d5f70SGabor Marton     addToFunctionSummaryMap(
1765db4d5f70SGabor Marton         "linkat",
176611d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy},
176711d2e63aSGabor Marton                   RetType{IntTy}),
176811d2e63aSGabor Marton         Summary(NoEvalCall)
1769febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1770db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1771db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
1772db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
1773db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
1774db4d5f70SGabor Marton 
1775db4d5f70SGabor Marton     // int unlink(const char *pathname);
1776febe7503SGabor Marton     addToFunctionSummaryMap("unlink",
1777febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1778febe7503SGabor Marton                             Summary(NoEvalCall)
1779febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
1780febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1781db4d5f70SGabor Marton 
1782db4d5f70SGabor Marton     // int unlinkat(int fd, const char *path, int flag);
1783db4d5f70SGabor Marton     addToFunctionSummaryMap(
1784db4d5f70SGabor Marton         "unlinkat",
178511d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}),
178611d2e63aSGabor Marton         Summary(NoEvalCall)
1787febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1788db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1789db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1790db4d5f70SGabor Marton 
1791a787a4edSGabor Marton     Optional<QualType> StructStatTy = lookupTy("stat");
1792a787a4edSGabor Marton     Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy);
1793a787a4edSGabor Marton     Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy);
1794db4d5f70SGabor Marton 
1795db4d5f70SGabor Marton     // int fstat(int fd, struct stat *statbuf);
1796db4d5f70SGabor Marton     addToFunctionSummaryMap(
179711d2e63aSGabor Marton         "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}),
179811d2e63aSGabor Marton         Summary(NoEvalCall)
1799febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1800a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1801db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1802db4d5f70SGabor Marton 
1803db4d5f70SGabor Marton     // int stat(const char *restrict path, struct stat *restrict buf);
180411d2e63aSGabor Marton     addToFunctionSummaryMap(
180511d2e63aSGabor Marton         "stat",
180611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
180711d2e63aSGabor Marton                   RetType{IntTy}),
180811d2e63aSGabor Marton         Summary(NoEvalCall)
1809febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1810db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1811db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1812db4d5f70SGabor Marton 
1813db4d5f70SGabor Marton     // int lstat(const char *restrict path, struct stat *restrict buf);
181411d2e63aSGabor Marton     addToFunctionSummaryMap(
181511d2e63aSGabor Marton         "lstat",
181611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
181711d2e63aSGabor Marton                   RetType{IntTy}),
181811d2e63aSGabor Marton         Summary(NoEvalCall)
1819febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1820db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1821db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1822db4d5f70SGabor Marton 
1823db4d5f70SGabor Marton     // int fstatat(int fd, const char *restrict path,
1824db4d5f70SGabor Marton     //             struct stat *restrict buf, int flag);
1825db4d5f70SGabor Marton     addToFunctionSummaryMap(
1826a787a4edSGabor Marton         "fstatat",
182711d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy,
182811d2e63aSGabor Marton                            StructStatPtrRestrictTy, IntTy},
182911d2e63aSGabor Marton                   RetType{IntTy}),
183011d2e63aSGabor Marton         Summary(NoEvalCall)
1831febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1832a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1833db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
1834db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
1835db4d5f70SGabor Marton 
1836db4d5f70SGabor Marton     // DIR *opendir(const char *name);
183711d2e63aSGabor Marton     addToFunctionSummaryMap(
183811d2e63aSGabor Marton         "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
183911d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1840db4d5f70SGabor Marton 
1841db4d5f70SGabor Marton     // DIR *fdopendir(int fd);
184211d2e63aSGabor Marton     addToFunctionSummaryMap("fdopendir",
184311d2e63aSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
184411d2e63aSGabor Marton                             Summary(NoEvalCall)
184511d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
184611d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1847db4d5f70SGabor Marton 
1848db4d5f70SGabor Marton     // int isatty(int fildes);
1849febe7503SGabor Marton     addToFunctionSummaryMap(
1850febe7503SGabor Marton         "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}),
185111d2e63aSGabor Marton         Summary(NoEvalCall)
1852febe7503SGabor Marton             .Case({ReturnValueCondition(WithinRange, Range(0, 1))})
1853febe7503SGabor Marton             .ArgConstraint(
1854febe7503SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1855db4d5f70SGabor Marton 
1856db4d5f70SGabor Marton     // FILE *popen(const char *command, const char *type);
185711d2e63aSGabor Marton     addToFunctionSummaryMap(
185811d2e63aSGabor Marton         "popen",
185911d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}),
186011d2e63aSGabor Marton         Summary(NoEvalCall)
1861db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1862db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1863db4d5f70SGabor Marton 
1864db4d5f70SGabor Marton     // int pclose(FILE *stream);
1865db4d5f70SGabor Marton     addToFunctionSummaryMap(
186611d2e63aSGabor Marton         "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
186711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1868db4d5f70SGabor Marton 
1869db4d5f70SGabor Marton     // int close(int fildes);
187011d2e63aSGabor Marton     addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}),
187111d2e63aSGabor Marton                             Summary(NoEvalCall)
1872febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
187311d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
1874d14c6316SGabor Marton                                     0, WithinRange, Range(-1, IntMax))));
1875db4d5f70SGabor Marton 
1876db4d5f70SGabor Marton     // long fpathconf(int fildes, int name);
187711d2e63aSGabor Marton     addToFunctionSummaryMap("fpathconf",
187811d2e63aSGabor Marton                             Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}),
187911d2e63aSGabor Marton                             Summary(NoEvalCall)
188011d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
188111d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1882db4d5f70SGabor Marton 
1883db4d5f70SGabor Marton     // long pathconf(const char *path, int name);
188411d2e63aSGabor Marton     addToFunctionSummaryMap(
188511d2e63aSGabor Marton         "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}),
188611d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1887db4d5f70SGabor Marton 
1888db4d5f70SGabor Marton     // FILE *fdopen(int fd, const char *mode);
1889db4d5f70SGabor Marton     addToFunctionSummaryMap(
1890a787a4edSGabor Marton         "fdopen",
189111d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}),
189211d2e63aSGabor Marton         Summary(NoEvalCall)
1893a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1894db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1895db4d5f70SGabor Marton 
1896db4d5f70SGabor Marton     // void rewinddir(DIR *dir);
1897db4d5f70SGabor Marton     addToFunctionSummaryMap(
189811d2e63aSGabor Marton         "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}),
189911d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1900db4d5f70SGabor Marton 
1901db4d5f70SGabor Marton     // void seekdir(DIR *dirp, long loc);
190211d2e63aSGabor Marton     addToFunctionSummaryMap(
190311d2e63aSGabor Marton         "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}),
190411d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1905db4d5f70SGabor Marton 
1906db4d5f70SGabor Marton     // int rand_r(unsigned int *seedp);
190711d2e63aSGabor Marton     addToFunctionSummaryMap(
190811d2e63aSGabor Marton         "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}),
190911d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1910db4d5f70SGabor Marton 
1911db4d5f70SGabor Marton     // int fileno(FILE *stream);
1912febe7503SGabor Marton     addToFunctionSummaryMap("fileno",
1913febe7503SGabor Marton                             Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1914febe7503SGabor Marton                             Summary(NoEvalCall)
1915febe7503SGabor Marton                                 .Case(ReturnsFileDescriptor)
1916febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1917db4d5f70SGabor Marton 
1918db4d5f70SGabor Marton     // int fseeko(FILE *stream, off_t offset, int whence);
1919a787a4edSGabor Marton     addToFunctionSummaryMap(
1920a787a4edSGabor Marton         "fseeko",
192111d2e63aSGabor Marton         Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
1922febe7503SGabor Marton         Summary(NoEvalCall)
1923febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
1924febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1925db4d5f70SGabor Marton 
1926db4d5f70SGabor Marton     // off_t ftello(FILE *stream);
1927db4d5f70SGabor Marton     addToFunctionSummaryMap(
192811d2e63aSGabor Marton         "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
192911d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1930db4d5f70SGabor Marton 
1931db4d5f70SGabor Marton     // void *mmap(void *addr, size_t length, int prot, int flags, int fd,
1932db4d5f70SGabor Marton     // off_t offset);
1933db4d5f70SGabor Marton     addToFunctionSummaryMap(
1934db4d5f70SGabor Marton         "mmap",
193511d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
193611d2e63aSGabor Marton                   RetType{VoidPtrTy}),
193711d2e63aSGabor Marton         Summary(NoEvalCall)
1938a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1939db4d5f70SGabor Marton             .ArgConstraint(
1940d14c6316SGabor Marton                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
1941db4d5f70SGabor Marton 
1942a787a4edSGabor Marton     Optional<QualType> Off64_tTy = lookupTy("off64_t");
1943db4d5f70SGabor Marton     // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
1944db4d5f70SGabor Marton     // off64_t offset);
1945db4d5f70SGabor Marton     addToFunctionSummaryMap(
1946db4d5f70SGabor Marton         "mmap64",
194711d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
194811d2e63aSGabor Marton                   RetType{VoidPtrTy}),
194911d2e63aSGabor Marton         Summary(NoEvalCall)
1950a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1951db4d5f70SGabor Marton             .ArgConstraint(
1952d14c6316SGabor Marton                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
1953db4d5f70SGabor Marton 
1954db4d5f70SGabor Marton     // int pipe(int fildes[2]);
1955febe7503SGabor Marton     addToFunctionSummaryMap("pipe",
1956febe7503SGabor Marton                             Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
1957febe7503SGabor Marton                             Summary(NoEvalCall)
1958febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
1959febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1960db4d5f70SGabor Marton 
1961db4d5f70SGabor Marton     // off_t lseek(int fildes, off_t offset, int whence);
1962db4d5f70SGabor Marton     addToFunctionSummaryMap(
196311d2e63aSGabor Marton         "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}),
196411d2e63aSGabor Marton         Summary(NoEvalCall)
1965a787a4edSGabor Marton             .ArgConstraint(
1966a787a4edSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1967db4d5f70SGabor Marton 
1968db4d5f70SGabor Marton     // ssize_t readlink(const char *restrict path, char *restrict buf,
1969db4d5f70SGabor Marton     //                  size_t bufsize);
1970db4d5f70SGabor Marton     addToFunctionSummaryMap(
1971db4d5f70SGabor Marton         "readlink",
197211d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
197311d2e63aSGabor Marton                   RetType{Ssize_tTy}),
197411d2e63aSGabor Marton         Summary(NoEvalCall)
1975b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1976b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
1977db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1978db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
1979db4d5f70SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1980db4d5f70SGabor Marton                                       /*BufSize=*/ArgNo(2)))
1981db4d5f70SGabor Marton             .ArgConstraint(
1982db4d5f70SGabor Marton                 ArgumentCondition(2, WithinRange, Range(0, SizeMax))));
1983db4d5f70SGabor Marton 
1984db4d5f70SGabor Marton     // ssize_t readlinkat(int fd, const char *restrict path,
1985db4d5f70SGabor Marton     //                    char *restrict buf, size_t bufsize);
1986db4d5f70SGabor Marton     addToFunctionSummaryMap(
1987a787a4edSGabor Marton         "readlinkat",
198811d2e63aSGabor Marton         Signature(
1989a787a4edSGabor Marton             ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
199011d2e63aSGabor Marton             RetType{Ssize_tTy}),
199111d2e63aSGabor Marton         Summary(NoEvalCall)
1992b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
1993b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
1994a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1995db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
1996db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2)))
1997db4d5f70SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
1998db4d5f70SGabor Marton                                       /*BufSize=*/ArgNo(3)))
1999a787a4edSGabor Marton             .ArgConstraint(
2000a787a4edSGabor Marton                 ArgumentCondition(3, WithinRange, Range(0, SizeMax))));
2001db4d5f70SGabor Marton 
2002db4d5f70SGabor Marton     // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char
2003db4d5f70SGabor Marton     // *newpath);
200411d2e63aSGabor Marton     addToFunctionSummaryMap(
200511d2e63aSGabor Marton         "renameat",
200611d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy},
200711d2e63aSGabor Marton                   RetType{IntTy}),
200811d2e63aSGabor Marton         Summary(NoEvalCall)
2009febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2010db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2011db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
2012db4d5f70SGabor Marton 
2013db4d5f70SGabor Marton     // char *realpath(const char *restrict file_name,
2014db4d5f70SGabor Marton     //                char *restrict resolved_name);
2015db4d5f70SGabor Marton     addToFunctionSummaryMap(
201611d2e63aSGabor Marton         "realpath",
201711d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
201811d2e63aSGabor Marton                   RetType{CharPtrTy}),
201911d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2020db4d5f70SGabor Marton 
2021a787a4edSGabor Marton     QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy));
2022db4d5f70SGabor Marton 
2023db4d5f70SGabor Marton     // int execv(const char *path, char *const argv[]);
202411d2e63aSGabor Marton     addToFunctionSummaryMap(
202511d2e63aSGabor Marton         "execv",
202611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2027febe7503SGabor Marton         Summary(NoEvalCall)
2028febe7503SGabor Marton             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
2029febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2030db4d5f70SGabor Marton 
2031db4d5f70SGabor Marton     // int execvp(const char *file, char *const argv[]);
203211d2e63aSGabor Marton     addToFunctionSummaryMap(
203311d2e63aSGabor Marton         "execvp",
203411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2035febe7503SGabor Marton         Summary(NoEvalCall)
2036febe7503SGabor Marton             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
2037febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2038db4d5f70SGabor Marton 
2039db4d5f70SGabor Marton     // int getopt(int argc, char * const argv[], const char *optstring);
2040db4d5f70SGabor Marton     addToFunctionSummaryMap(
2041db4d5f70SGabor Marton         "getopt",
204211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
204311d2e63aSGabor Marton                   RetType{IntTy}),
204411d2e63aSGabor Marton         Summary(NoEvalCall)
2045febe7503SGabor Marton             .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))})
2046db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2047db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2048db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
20493ff220deSGabor Marton 
2050a787a4edSGabor Marton     Optional<QualType> StructSockaddrTy = lookupTy("sockaddr");
2051a787a4edSGabor Marton     Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy);
2052a787a4edSGabor Marton     Optional<QualType> ConstStructSockaddrPtrTy =
2053a787a4edSGabor Marton         getPointerTy(getConstTy(StructSockaddrTy));
2054a787a4edSGabor Marton     Optional<QualType> StructSockaddrPtrRestrictTy =
2055a787a4edSGabor Marton         getRestrictTy(StructSockaddrPtrTy);
2056a787a4edSGabor Marton     Optional<QualType> ConstStructSockaddrPtrRestrictTy =
2057a787a4edSGabor Marton         getRestrictTy(ConstStructSockaddrPtrTy);
2058a787a4edSGabor Marton     Optional<QualType> Socklen_tTy = lookupTy("socklen_t");
2059a787a4edSGabor Marton     Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy);
2060a787a4edSGabor Marton     Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
2061a787a4edSGabor Marton     Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy);
20623ff220deSGabor Marton 
20633ff220deSGabor Marton     // In 'socket.h' of some libc implementations with C99, sockaddr parameter
20643ff220deSGabor Marton     // is a transparent union of the underlying sockaddr_ family of pointers
20653ff220deSGabor Marton     // instead of being a pointer to struct sockaddr. In these cases, the
20663ff220deSGabor Marton     // standardized signature will not match, thus we try to match with another
20673ff220deSGabor Marton     // signature that has the joker Irrelevant type. We also remove those
20683ff220deSGabor Marton     // constraints which require pointer types for the sockaddr param.
2069a787a4edSGabor Marton     auto Accept =
2070a787a4edSGabor Marton         Summary(NoEvalCall)
2071febe7503SGabor Marton             .Case(ReturnsFileDescriptor)
2072a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
20733ff220deSGabor Marton     if (!addToFunctionSummaryMap(
20743ff220deSGabor Marton             "accept",
20753ff220deSGabor Marton             // int accept(int socket, struct sockaddr *restrict address,
20763ff220deSGabor Marton             //            socklen_t *restrict address_len);
2077a787a4edSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2078a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
20793ff220deSGabor Marton                       RetType{IntTy}),
20803ff220deSGabor Marton             Accept))
20813ff220deSGabor Marton       addToFunctionSummaryMap(
20823ff220deSGabor Marton           "accept",
2083a787a4edSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
20843ff220deSGabor Marton                     RetType{IntTy}),
20853ff220deSGabor Marton           Accept);
20863ff220deSGabor Marton 
20873ff220deSGabor Marton     // int bind(int socket, const struct sockaddr *address, socklen_t
20883ff220deSGabor Marton     //          address_len);
20893ff220deSGabor Marton     if (!addToFunctionSummaryMap(
20903ff220deSGabor Marton             "bind",
209111d2e63aSGabor Marton             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
209211d2e63aSGabor Marton                       RetType{IntTy}),
209311d2e63aSGabor Marton             Summary(NoEvalCall)
2094b40b3196SGabor Marton                 .Case(ReturnsZeroOrMinusOne)
20953ff220deSGabor Marton                 .ArgConstraint(
20963ff220deSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
20973ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
20983ff220deSGabor Marton                 .ArgConstraint(
20993ff220deSGabor Marton                     BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))
2100a787a4edSGabor Marton                 .ArgConstraint(
2101a787a4edSGabor Marton                     ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))))
21023ff220deSGabor Marton       // Do not add constraints on sockaddr.
21033ff220deSGabor Marton       addToFunctionSummaryMap(
210411d2e63aSGabor Marton           "bind",
210511d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
210611d2e63aSGabor Marton           Summary(NoEvalCall)
2107b40b3196SGabor Marton               .Case(ReturnsZeroOrMinusOne)
21083ff220deSGabor Marton               .ArgConstraint(
21093ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax)))
211011d2e63aSGabor Marton               .ArgConstraint(
211111d2e63aSGabor Marton                   ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))));
21123ff220deSGabor Marton 
21133ff220deSGabor Marton     // int getpeername(int socket, struct sockaddr *restrict address,
21143ff220deSGabor Marton     //                 socklen_t *restrict address_len);
21153ff220deSGabor Marton     if (!addToFunctionSummaryMap(
211611d2e63aSGabor Marton             "getpeername",
211711d2e63aSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2118a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
211911d2e63aSGabor Marton                       RetType{IntTy}),
212011d2e63aSGabor Marton             Summary(NoEvalCall)
2121b40b3196SGabor Marton                 .Case(ReturnsZeroOrMinusOne)
212211d2e63aSGabor Marton                 .ArgConstraint(
212311d2e63aSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
21243ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
21253ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(2)))))
21263ff220deSGabor Marton       addToFunctionSummaryMap(
21273ff220deSGabor Marton           "getpeername",
212811d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
212911d2e63aSGabor Marton                     RetType{IntTy}),
213011d2e63aSGabor Marton           Summary(NoEvalCall)
2131b40b3196SGabor Marton               .Case(ReturnsZeroOrMinusOne)
21323ff220deSGabor Marton               .ArgConstraint(
21333ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
21343ff220deSGabor Marton 
21353ff220deSGabor Marton     // int getsockname(int socket, struct sockaddr *restrict address,
21363ff220deSGabor Marton     //                 socklen_t *restrict address_len);
21373ff220deSGabor Marton     if (!addToFunctionSummaryMap(
213811d2e63aSGabor Marton             "getsockname",
213911d2e63aSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2140a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
214111d2e63aSGabor Marton                       RetType{IntTy}),
214211d2e63aSGabor Marton             Summary(NoEvalCall)
2143b40b3196SGabor Marton                 .Case(ReturnsZeroOrMinusOne)
214411d2e63aSGabor Marton                 .ArgConstraint(
214511d2e63aSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
21463ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
21473ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(2)))))
21483ff220deSGabor Marton       addToFunctionSummaryMap(
21493ff220deSGabor Marton           "getsockname",
215011d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
215111d2e63aSGabor Marton                     RetType{IntTy}),
215211d2e63aSGabor Marton           Summary(NoEvalCall)
2153b40b3196SGabor Marton               .Case(ReturnsZeroOrMinusOne)
21543ff220deSGabor Marton               .ArgConstraint(
21553ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
21563ff220deSGabor Marton 
21573ff220deSGabor Marton     // int connect(int socket, const struct sockaddr *address, socklen_t
21583ff220deSGabor Marton     //             address_len);
21593ff220deSGabor Marton     if (!addToFunctionSummaryMap(
21603ff220deSGabor Marton             "connect",
216111d2e63aSGabor Marton             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
216211d2e63aSGabor Marton                       RetType{IntTy}),
216311d2e63aSGabor Marton             Summary(NoEvalCall)
2164b40b3196SGabor Marton                 .Case(ReturnsZeroOrMinusOne)
21653ff220deSGabor Marton                 .ArgConstraint(
21663ff220deSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
21673ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))))
21683ff220deSGabor Marton       addToFunctionSummaryMap(
216911d2e63aSGabor Marton           "connect",
217011d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
217111d2e63aSGabor Marton           Summary(NoEvalCall)
2172b40b3196SGabor Marton               .Case(ReturnsZeroOrMinusOne)
217311d2e63aSGabor Marton               .ArgConstraint(
217411d2e63aSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
21753ff220deSGabor Marton 
2176a787a4edSGabor Marton     auto Recvfrom =
2177a787a4edSGabor Marton         Summary(NoEvalCall)
2178b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2179b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2180a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
21813ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
21823ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2)));
2183a787a4edSGabor Marton     if (!addToFunctionSummaryMap(
21843ff220deSGabor Marton             "recvfrom",
21853ff220deSGabor Marton             // ssize_t recvfrom(int socket, void *restrict buffer,
21863ff220deSGabor Marton             //                  size_t length,
21873ff220deSGabor Marton             //                  int flags, struct sockaddr *restrict address,
21883ff220deSGabor Marton             //                  socklen_t *restrict address_len);
21893ff220deSGabor Marton             Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2190a787a4edSGabor Marton                                StructSockaddrPtrRestrictTy,
2191a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
2192a787a4edSGabor Marton                       RetType{Ssize_tTy}),
21933ff220deSGabor Marton             Recvfrom))
21943ff220deSGabor Marton       addToFunctionSummaryMap(
21953ff220deSGabor Marton           "recvfrom",
21963ff220deSGabor Marton           Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2197a787a4edSGabor Marton                              Irrelevant, Socklen_tPtrRestrictTy},
2198a787a4edSGabor Marton                     RetType{Ssize_tTy}),
21993ff220deSGabor Marton           Recvfrom);
22003ff220deSGabor Marton 
2201a787a4edSGabor Marton     auto Sendto =
2202a787a4edSGabor Marton         Summary(NoEvalCall)
2203b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2204b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2205a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
22063ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
22073ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2)));
2208a787a4edSGabor Marton     if (!addToFunctionSummaryMap(
22093ff220deSGabor Marton             "sendto",
22103ff220deSGabor Marton             // ssize_t sendto(int socket, const void *message, size_t length,
22113ff220deSGabor Marton             //                int flags, const struct sockaddr *dest_addr,
22123ff220deSGabor Marton             //                socklen_t dest_len);
22133ff220deSGabor Marton             Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy,
2214a787a4edSGabor Marton                                ConstStructSockaddrPtrTy, Socklen_tTy},
2215a787a4edSGabor Marton                       RetType{Ssize_tTy}),
22163ff220deSGabor Marton             Sendto))
22173ff220deSGabor Marton       addToFunctionSummaryMap(
22183ff220deSGabor Marton           "sendto",
22193ff220deSGabor Marton           Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant,
2220a787a4edSGabor Marton                              Socklen_tTy},
2221a787a4edSGabor Marton                     RetType{Ssize_tTy}),
22223ff220deSGabor Marton           Sendto);
22233ff220deSGabor Marton 
22243ff220deSGabor Marton     // int listen(int sockfd, int backlog);
222511d2e63aSGabor Marton     addToFunctionSummaryMap("listen",
222611d2e63aSGabor Marton                             Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
222711d2e63aSGabor Marton                             Summary(NoEvalCall)
2228b40b3196SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
222911d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
223011d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
22313ff220deSGabor Marton 
22323ff220deSGabor Marton     // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
22333ff220deSGabor Marton     addToFunctionSummaryMap(
2234a787a4edSGabor Marton         "recv",
223511d2e63aSGabor Marton         Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy},
223611d2e63aSGabor Marton                   RetType{Ssize_tTy}),
223711d2e63aSGabor Marton         Summary(NoEvalCall)
2238b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2239b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2240a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
22413ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
22423ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2))));
22433ff220deSGabor Marton 
2244a787a4edSGabor Marton     Optional<QualType> StructMsghdrTy = lookupTy("msghdr");
2245a787a4edSGabor Marton     Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy);
2246a787a4edSGabor Marton     Optional<QualType> ConstStructMsghdrPtrTy =
2247a787a4edSGabor Marton         getPointerTy(getConstTy(StructMsghdrTy));
22483ff220deSGabor Marton 
22493ff220deSGabor Marton     // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
2250b40b3196SGabor Marton     addToFunctionSummaryMap(
2251b40b3196SGabor Marton         "recvmsg",
225211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
225311d2e63aSGabor Marton                   RetType{Ssize_tTy}),
225411d2e63aSGabor Marton         Summary(NoEvalCall)
2255b40b3196SGabor Marton             .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2256b40b3196SGabor Marton             .ArgConstraint(
2257b40b3196SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
22583ff220deSGabor Marton 
22593ff220deSGabor Marton     // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
22603ff220deSGabor Marton     addToFunctionSummaryMap(
226111d2e63aSGabor Marton         "sendmsg",
226211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
226311d2e63aSGabor Marton                   RetType{Ssize_tTy}),
226411d2e63aSGabor Marton         Summary(NoEvalCall)
2265b40b3196SGabor Marton             .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
226611d2e63aSGabor Marton             .ArgConstraint(
226711d2e63aSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
22683ff220deSGabor Marton 
22693ff220deSGabor Marton     // int setsockopt(int socket, int level, int option_name,
22703ff220deSGabor Marton     //                const void *option_value, socklen_t option_len);
22713ff220deSGabor Marton     addToFunctionSummaryMap(
22723ff220deSGabor Marton         "setsockopt",
227311d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
227411d2e63aSGabor Marton                   RetType{IntTy}),
227511d2e63aSGabor Marton         Summary(NoEvalCall)
2276b40b3196SGabor Marton             .Case(ReturnsZeroOrMinusOne)
22773ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(3)))
22783ff220deSGabor Marton             .ArgConstraint(
22793ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
22803ff220deSGabor Marton             .ArgConstraint(
2281a787a4edSGabor Marton                 ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax))));
22823ff220deSGabor Marton 
22833ff220deSGabor Marton     // int getsockopt(int socket, int level, int option_name,
22843ff220deSGabor Marton     //                void *restrict option_value,
22853ff220deSGabor Marton     //                socklen_t *restrict option_len);
22863ff220deSGabor Marton     addToFunctionSummaryMap(
228711d2e63aSGabor Marton         "getsockopt",
228811d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy,
2289a787a4edSGabor Marton                            Socklen_tPtrRestrictTy},
229011d2e63aSGabor Marton                   RetType{IntTy}),
229111d2e63aSGabor Marton         Summary(NoEvalCall)
2292b40b3196SGabor Marton             .Case(ReturnsZeroOrMinusOne)
22933ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(3)))
22943ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(4))));
22953ff220deSGabor Marton 
22963ff220deSGabor Marton     // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
22973ff220deSGabor Marton     addToFunctionSummaryMap(
2298a787a4edSGabor Marton         "send",
229911d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy},
230011d2e63aSGabor Marton                   RetType{Ssize_tTy}),
230111d2e63aSGabor Marton         Summary(NoEvalCall)
2302b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2303b40b3196SGabor Marton                    ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2304a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
23053ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
23063ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2))));
23073ff220deSGabor Marton 
23083ff220deSGabor Marton     // int socketpair(int domain, int type, int protocol, int sv[2]);
230911d2e63aSGabor Marton     addToFunctionSummaryMap(
231011d2e63aSGabor Marton         "socketpair",
231111d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}),
2312b40b3196SGabor Marton         Summary(NoEvalCall)
2313b40b3196SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2314b40b3196SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
23153ff220deSGabor Marton 
23163ff220deSGabor Marton     // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
23173ff220deSGabor Marton     //                 char *restrict node, socklen_t nodelen,
23183ff220deSGabor Marton     //                 char *restrict service,
23193ff220deSGabor Marton     //                 socklen_t servicelen, int flags);
23203ff220deSGabor Marton     //
23213ff220deSGabor Marton     // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr
23223ff220deSGabor Marton     // parameter is never handled as a transparent union in netdb.h
23233ff220deSGabor Marton     addToFunctionSummaryMap(
23243ff220deSGabor Marton         "getnameinfo",
232511d2e63aSGabor Marton         Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy,
2326a787a4edSGabor Marton                            CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy,
2327a787a4edSGabor Marton                            Socklen_tTy, IntTy},
232811d2e63aSGabor Marton                   RetType{IntTy}),
232911d2e63aSGabor Marton         Summary(NoEvalCall)
23303ff220deSGabor Marton             .ArgConstraint(
23313ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
23323ff220deSGabor Marton             .ArgConstraint(
2333a787a4edSGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax)))
23343ff220deSGabor Marton             .ArgConstraint(
23353ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3)))
23363ff220deSGabor Marton             .ArgConstraint(
2337a787a4edSGabor Marton                 ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax)))
23383ff220deSGabor Marton             .ArgConstraint(
23393ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
23403ff220deSGabor Marton             .ArgConstraint(
2341a787a4edSGabor Marton                 ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax))));
2342f0b9dbcfSGabor Marton 
2343f0b9dbcfSGabor Marton     Optional<QualType> StructUtimbufTy = lookupTy("utimbuf");
2344f0b9dbcfSGabor Marton     Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy);
2345f0b9dbcfSGabor Marton 
2346f0b9dbcfSGabor Marton     // int utime(const char *filename, struct utimbuf *buf);
2347f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
234811d2e63aSGabor Marton         "utime",
234911d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}),
2350febe7503SGabor Marton         Summary(NoEvalCall)
2351febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2352febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2353f0b9dbcfSGabor Marton 
2354f0b9dbcfSGabor Marton     Optional<QualType> StructTimespecTy = lookupTy("timespec");
2355f0b9dbcfSGabor Marton     Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy);
2356f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTimespecPtrTy =
2357f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTimespecTy));
2358f0b9dbcfSGabor Marton 
2359f0b9dbcfSGabor Marton     // int futimens(int fd, const struct timespec times[2]);
2360f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
236111d2e63aSGabor Marton         "futimens",
236211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}),
236311d2e63aSGabor Marton         Summary(NoEvalCall)
2364febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
236511d2e63aSGabor Marton             .ArgConstraint(
236611d2e63aSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2367f0b9dbcfSGabor Marton 
2368f0b9dbcfSGabor Marton     // int utimensat(int dirfd, const char *pathname,
2369f0b9dbcfSGabor Marton     //               const struct timespec times[2], int flags);
2370febe7503SGabor Marton     addToFunctionSummaryMap("utimensat",
2371febe7503SGabor Marton                             Signature(ArgTypes{IntTy, ConstCharPtrTy,
2372febe7503SGabor Marton                                                ConstStructTimespecPtrTy, IntTy},
237311d2e63aSGabor Marton                                       RetType{IntTy}),
2374febe7503SGabor Marton                             Summary(NoEvalCall)
2375febe7503SGabor Marton                                 .Case(ReturnsZeroOrMinusOne)
2376febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(1))));
2377f0b9dbcfSGabor Marton 
2378f0b9dbcfSGabor Marton     Optional<QualType> StructTimevalTy = lookupTy("timeval");
2379f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTimevalPtrTy =
2380f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTimevalTy));
2381f0b9dbcfSGabor Marton 
2382f0b9dbcfSGabor Marton     // int utimes(const char *filename, const struct timeval times[2]);
2383f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
238411d2e63aSGabor Marton         "utimes",
238511d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
238611d2e63aSGabor Marton                   RetType{IntTy}),
2387febe7503SGabor Marton         Summary(NoEvalCall)
2388febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2389febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2390f0b9dbcfSGabor Marton 
2391f0b9dbcfSGabor Marton     // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
2392f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2393f0b9dbcfSGabor Marton         "nanosleep",
239411d2e63aSGabor Marton         Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
239511d2e63aSGabor Marton                   RetType{IntTy}),
2396febe7503SGabor Marton         Summary(NoEvalCall)
2397febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2398febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2399f0b9dbcfSGabor Marton 
2400f0b9dbcfSGabor Marton     Optional<QualType> Time_tTy = lookupTy("time_t");
2401f0b9dbcfSGabor Marton     Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy));
2402f0b9dbcfSGabor Marton     Optional<QualType> ConstTime_tPtrRestrictTy =
2403f0b9dbcfSGabor Marton         getRestrictTy(ConstTime_tPtrTy);
2404f0b9dbcfSGabor Marton 
2405f0b9dbcfSGabor Marton     Optional<QualType> StructTmTy = lookupTy("tm");
2406f0b9dbcfSGabor Marton     Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy);
2407f0b9dbcfSGabor Marton     Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy);
2408f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTmPtrTy =
2409f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTmTy));
2410f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTmPtrRestrictTy =
2411f0b9dbcfSGabor Marton         getRestrictTy(ConstStructTmPtrTy);
2412f0b9dbcfSGabor Marton 
2413f0b9dbcfSGabor Marton     // struct tm * localtime(const time_t *tp);
2414f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2415f0b9dbcfSGabor Marton         "localtime",
241611d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
241711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2418f0b9dbcfSGabor Marton 
2419f0b9dbcfSGabor Marton     // struct tm *localtime_r(const time_t *restrict timer,
2420f0b9dbcfSGabor Marton     //                        struct tm *restrict result);
2421f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2422f0b9dbcfSGabor Marton         "localtime_r",
242311d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
242411d2e63aSGabor Marton                   RetType{StructTmPtrTy}),
242511d2e63aSGabor Marton         Summary(NoEvalCall)
2426f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2427f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2428f0b9dbcfSGabor Marton 
2429f0b9dbcfSGabor Marton     // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
2430f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2431f0b9dbcfSGabor Marton         "asctime_r",
243211d2e63aSGabor Marton         Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
243311d2e63aSGabor Marton                   RetType{CharPtrTy}),
243411d2e63aSGabor Marton         Summary(NoEvalCall)
2435f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2436f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2437f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2438f0b9dbcfSGabor Marton                                       /*MinBufSize=*/BVF.getValue(26, IntTy))));
2439f0b9dbcfSGabor Marton 
2440f0b9dbcfSGabor Marton     // char *ctime_r(const time_t *timep, char *buf);
244111d2e63aSGabor Marton     addToFunctionSummaryMap(
244211d2e63aSGabor Marton         "ctime_r",
244311d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}),
244411d2e63aSGabor Marton         Summary(NoEvalCall)
2445f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2446f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2447f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(
2448f0b9dbcfSGabor Marton                 /*Buffer=*/ArgNo(1),
2449f0b9dbcfSGabor Marton                 /*MinBufSize=*/BVF.getValue(26, IntTy))));
2450f0b9dbcfSGabor Marton 
2451f0b9dbcfSGabor Marton     // struct tm *gmtime_r(const time_t *restrict timer,
2452f0b9dbcfSGabor Marton     //                     struct tm *restrict result);
2453f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2454f0b9dbcfSGabor Marton         "gmtime_r",
245511d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
245611d2e63aSGabor Marton                   RetType{StructTmPtrTy}),
245711d2e63aSGabor Marton         Summary(NoEvalCall)
2458f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2459f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2460f0b9dbcfSGabor Marton 
2461f0b9dbcfSGabor Marton     // struct tm * gmtime(const time_t *tp);
2462f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
246311d2e63aSGabor Marton         "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
246411d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2465f0b9dbcfSGabor Marton 
2466f0b9dbcfSGabor Marton     Optional<QualType> Clockid_tTy = lookupTy("clockid_t");
2467f0b9dbcfSGabor Marton 
2468f0b9dbcfSGabor Marton     // int clock_gettime(clockid_t clock_id, struct timespec *tp);
246911d2e63aSGabor Marton     addToFunctionSummaryMap(
247011d2e63aSGabor Marton         "clock_gettime",
247111d2e63aSGabor Marton         Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}),
2472febe7503SGabor Marton         Summary(NoEvalCall)
2473febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2474febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2475f0b9dbcfSGabor Marton 
2476f0b9dbcfSGabor Marton     Optional<QualType> StructItimervalTy = lookupTy("itimerval");
2477f0b9dbcfSGabor Marton     Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy);
2478f0b9dbcfSGabor Marton 
2479f0b9dbcfSGabor Marton     // int getitimer(int which, struct itimerval *curr_value);
248011d2e63aSGabor Marton     addToFunctionSummaryMap(
248111d2e63aSGabor Marton         "getitimer",
248211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}),
2483febe7503SGabor Marton         Summary(NoEvalCall)
2484febe7503SGabor Marton             .Case(ReturnsZeroOrMinusOne)
2485febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2486d0128058SGabor Marton 
2487d0128058SGabor Marton     Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
2488d0128058SGabor Marton     Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy);
2489d0128058SGabor Marton     Optional<QualType> Pthread_tTy = lookupTy("pthread_t");
2490d0128058SGabor Marton     Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy);
2491d0128058SGabor Marton     Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy);
2492d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t");
2493d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy);
2494d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tPtrRestrictTy =
2495d0128058SGabor Marton         getRestrictTy(Pthread_mutex_tPtrTy);
2496d0128058SGabor Marton     Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t");
2497d0128058SGabor Marton     Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy);
2498d0128058SGabor Marton     Optional<QualType> ConstPthread_attr_tPtrTy =
2499d0128058SGabor Marton         getPointerTy(getConstTy(Pthread_attr_tTy));
2500d0128058SGabor Marton     Optional<QualType> ConstPthread_attr_tPtrRestrictTy =
2501d0128058SGabor Marton         getRestrictTy(ConstPthread_attr_tPtrTy);
2502d0128058SGabor Marton     Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t");
2503d0128058SGabor Marton     Optional<QualType> ConstPthread_mutexattr_tPtrTy =
2504d0128058SGabor Marton         getPointerTy(getConstTy(Pthread_mutexattr_tTy));
2505d0128058SGabor Marton     Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy =
2506d0128058SGabor Marton         getRestrictTy(ConstPthread_mutexattr_tPtrTy);
2507d0128058SGabor Marton 
2508d0128058SGabor Marton     QualType PthreadStartRoutineTy = getPointerTy(
2509d0128058SGabor Marton         ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy,
2510d0128058SGabor Marton                              FunctionProtoType::ExtProtoInfo()));
2511d0128058SGabor Marton 
2512d0128058SGabor Marton     // int pthread_cond_signal(pthread_cond_t *cond);
2513d0128058SGabor Marton     // int pthread_cond_broadcast(pthread_cond_t *cond);
2514d0128058SGabor Marton     addToFunctionSummaryMap(
2515d0128058SGabor Marton         {"pthread_cond_signal", "pthread_cond_broadcast"},
2516d0128058SGabor Marton         Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}),
2517d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2518d0128058SGabor Marton 
2519d0128058SGabor Marton     // int pthread_create(pthread_t *restrict thread,
2520d0128058SGabor Marton     //                    const pthread_attr_t *restrict attr,
2521d0128058SGabor Marton     //                    void *(*start_routine)(void*), void *restrict arg);
2522d0128058SGabor Marton     addToFunctionSummaryMap(
2523d0128058SGabor Marton         "pthread_create",
2524d0128058SGabor Marton         Signature(ArgTypes{Pthread_tPtrRestrictTy,
2525d0128058SGabor Marton                            ConstPthread_attr_tPtrRestrictTy,
2526d0128058SGabor Marton                            PthreadStartRoutineTy, VoidPtrRestrictTy},
2527d0128058SGabor Marton                   RetType{IntTy}),
2528d0128058SGabor Marton         Summary(NoEvalCall)
2529d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2530d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
2531d0128058SGabor Marton 
2532d0128058SGabor Marton     // int pthread_attr_destroy(pthread_attr_t *attr);
2533d0128058SGabor Marton     // int pthread_attr_init(pthread_attr_t *attr);
2534d0128058SGabor Marton     addToFunctionSummaryMap(
2535d0128058SGabor Marton         {"pthread_attr_destroy", "pthread_attr_init"},
2536d0128058SGabor Marton         Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}),
2537d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2538d0128058SGabor Marton 
2539d0128058SGabor Marton     // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
2540d0128058SGabor Marton     //                               size_t *restrict stacksize);
2541d0128058SGabor Marton     // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
2542d0128058SGabor Marton     //                               size_t *restrict guardsize);
2543d0128058SGabor Marton     addToFunctionSummaryMap(
2544d0128058SGabor Marton         {"pthread_attr_getstacksize", "pthread_attr_getguardsize"},
2545d0128058SGabor Marton         Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy},
2546d0128058SGabor Marton                   RetType{IntTy}),
2547d0128058SGabor Marton         Summary(NoEvalCall)
2548d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2549d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2550d0128058SGabor Marton 
2551d0128058SGabor Marton     // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
2552d0128058SGabor Marton     // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
2553d0128058SGabor Marton     addToFunctionSummaryMap(
2554d0128058SGabor Marton         {"pthread_attr_setstacksize", "pthread_attr_setguardsize"},
2555d0128058SGabor Marton         Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}),
2556d0128058SGabor Marton         Summary(NoEvalCall)
2557d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2558d0128058SGabor Marton             .ArgConstraint(
2559d0128058SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
2560d0128058SGabor Marton 
2561d0128058SGabor Marton     // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
2562d0128058SGabor Marton     //                        pthread_mutexattr_t *restrict attr);
2563d0128058SGabor Marton     addToFunctionSummaryMap(
2564d0128058SGabor Marton         "pthread_mutex_init",
2565d0128058SGabor Marton         Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy,
2566d0128058SGabor Marton                            ConstPthread_mutexattr_tPtrRestrictTy},
2567d0128058SGabor Marton                   RetType{IntTy}),
2568d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2569d0128058SGabor Marton 
2570d0128058SGabor Marton     // int pthread_mutex_destroy(pthread_mutex_t *mutex);
2571d0128058SGabor Marton     // int pthread_mutex_lock(pthread_mutex_t *mutex);
2572d0128058SGabor Marton     // int pthread_mutex_trylock(pthread_mutex_t *mutex);
2573d0128058SGabor Marton     // int pthread_mutex_unlock(pthread_mutex_t *mutex);
2574d0128058SGabor Marton     addToFunctionSummaryMap(
2575d0128058SGabor Marton         {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock",
2576d0128058SGabor Marton          "pthread_mutex_unlock"},
2577d0128058SGabor Marton         Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}),
2578d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2579db4d5f70SGabor Marton   }
2580db4d5f70SGabor Marton 
25811525232eSGabor Marton   // Functions for testing.
25821525232eSGabor Marton   if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
258362e747f6SGabor Marton     addToFunctionSummaryMap(
2584a7cb951fSGabor Marton         "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2585a7cb951fSGabor Marton         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2586a7cb951fSGabor Marton 
2587a7cb951fSGabor Marton     // Test range values.
2588a7cb951fSGabor Marton     addToFunctionSummaryMap(
2589a7cb951fSGabor Marton         "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2590a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2591a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2592a7cb951fSGabor Marton     addToFunctionSummaryMap(
2593a7cb951fSGabor Marton         "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2594a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2595a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2))));
2596a7cb951fSGabor Marton     addToFunctionSummaryMap("__range_1_2__4_5",
2597a7cb951fSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
2598a7cb951fSGabor Marton                             Summary(EvalCallAsPure)
2599a7cb951fSGabor Marton                                 .ArgConstraint(ArgumentCondition(
2600a7cb951fSGabor Marton                                     0U, WithinRange, Range({1, 2}, {4, 5}))));
2601a7cb951fSGabor Marton 
2602a7cb951fSGabor Marton     // Test range kind.
2603a7cb951fSGabor Marton     addToFunctionSummaryMap(
2604a7cb951fSGabor Marton         "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2605a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2606a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2607a7cb951fSGabor Marton     addToFunctionSummaryMap(
2608a7cb951fSGabor Marton         "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2609a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2610a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))));
2611a7cb951fSGabor Marton 
2612a7cb951fSGabor Marton     addToFunctionSummaryMap(
261362e747f6SGabor Marton         "__two_constrained_args",
261411d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
261511d2e63aSGabor Marton         Summary(EvalCallAsPure)
261662e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))
261762e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1))));
261862e747f6SGabor Marton     addToFunctionSummaryMap(
261911d2e63aSGabor Marton         "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}),
262011d2e63aSGabor Marton         Summary(EvalCallAsPure)
262162e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))
262262e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2))));
262362e747f6SGabor Marton     addToFunctionSummaryMap(
262462e747f6SGabor Marton         "__defaultparam",
262511d2e63aSGabor Marton         Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}),
262611d2e63aSGabor Marton         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
262711d2e63aSGabor Marton     addToFunctionSummaryMap(
262811d2e63aSGabor Marton         "__variadic",
262911d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}),
263011d2e63aSGabor Marton         Summary(EvalCallAsPure)
26318f961399SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
263262e747f6SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2633bd03ef19SGabor Marton     addToFunctionSummaryMap(
2634bd03ef19SGabor Marton         "__buf_size_arg_constraint",
263511d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}),
263611d2e63aSGabor Marton         Summary(EvalCallAsPure)
2637bd03ef19SGabor Marton             .ArgConstraint(
2638bd03ef19SGabor Marton                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))));
263941928c97SGabor Marton     addToFunctionSummaryMap(
264041928c97SGabor Marton         "__buf_size_arg_constraint_mul",
264111d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}),
264211d2e63aSGabor Marton         Summary(EvalCallAsPure)
264341928c97SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
264441928c97SGabor Marton                                       /*BufSizeMultiplier=*/ArgNo(2))));
2645fe0972d3SGabor Marton     addToFunctionSummaryMap(
2646f0b9dbcfSGabor Marton         "__buf_size_arg_constraint_concrete",
264711d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}),
264811d2e63aSGabor Marton         Summary(EvalCallAsPure)
2649f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0),
2650f0b9dbcfSGabor Marton                                       /*BufSize=*/BVF.getValue(10, IntTy))));
2651f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2652fe0972d3SGabor Marton         {"__test_restrict_param_0", "__test_restrict_param_1",
2653fe0972d3SGabor Marton          "__test_restrict_param_2"},
2654fe0972d3SGabor Marton         Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
2655fe0972d3SGabor Marton         Summary(EvalCallAsPure));
26561525232eSGabor Marton   }
2657c7635040SValeriy Savchenko 
2658c7635040SValeriy Savchenko   SummariesInitialized = true;
2659bba497fbSArtem Dergachev }
2660bba497fbSArtem Dergachev 
2661bba497fbSArtem Dergachev void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
2662ff4492c8SGabor Marton   auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
2663*edde4efcSBalazs Benics   const AnalyzerOptions &Opts = mgr.getAnalyzerOptions();
2664ff4492c8SGabor Marton   Checker->DisplayLoadedSummaries =
2665*edde4efcSBalazs Benics       Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries");
2666*edde4efcSBalazs Benics   Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX");
2667*edde4efcSBalazs Benics   Checker->ShouldAssumeControlledEnvironment =
2668*edde4efcSBalazs Benics       Opts.ShouldAssumeControlledEnvironment;
2669bba497fbSArtem Dergachev }
2670058a7a45SKristof Umann 
267125bbe234SZurab Tsinadze bool ento::shouldRegisterStdCLibraryFunctionsChecker(
267225bbe234SZurab Tsinadze     const CheckerManager &mgr) {
2673058a7a45SKristof Umann   return true;
2674058a7a45SKristof Umann }
267594061df6SGabor Marton 
267694061df6SGabor Marton #define REGISTER_CHECKER(name)                                                 \
267794061df6SGabor Marton   void ento::register##name(CheckerManager &mgr) {                             \
267894061df6SGabor Marton     StdLibraryFunctionsChecker *checker =                                      \
267994061df6SGabor Marton         mgr.getChecker<StdLibraryFunctionsChecker>();                          \
268094061df6SGabor Marton     checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
268194061df6SGabor Marton     checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
268294061df6SGabor Marton         mgr.getCurrentCheckerName();                                           \
268394061df6SGabor Marton   }                                                                            \
268494061df6SGabor Marton                                                                                \
2685bda3dd0dSKirstóf Umann   bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
268694061df6SGabor Marton 
268794061df6SGabor Marton REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
26881525232eSGabor Marton REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
2689