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 //===----------------------------------------------------------------------===//
42bba497fbSArtem Dergachev 
43957014daSBalázs Kéri #include "ErrnoModeling.h"
4476a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
4594061df6SGabor Marton #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
46bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/Checker.h"
47bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/CheckerManager.h"
48bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
49bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
50536456a7SGabor Marton #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
519b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
52a7cb951fSGabor Marton #include "llvm/ADT/SmallString.h"
53a7cb951fSGabor Marton #include "llvm/ADT/StringExtras.h"
54a7cb951fSGabor Marton 
55a7cb951fSGabor Marton #include <string>
56bba497fbSArtem Dergachev 
57bba497fbSArtem Dergachev using namespace clang;
58bba497fbSArtem Dergachev using namespace clang::ento;
59bba497fbSArtem Dergachev 
60957014daSBalázs Kéri /// Produce a textual description of the state of \c errno (this describes the
61957014daSBalázs Kéri /// way how it is allowed to be used).
62957014daSBalázs Kéri /// The returned string is insertable into a longer warning message (in the form
63957014daSBalázs Kéri /// "the value 'errno' <...>").
64957014daSBalázs Kéri /// Currently only the \c errno_modeling::MustNotBeChecked state is supported.
65957014daSBalázs Kéri /// But later other kind of errno state may be needed if functions with special
66957014daSBalázs Kéri /// handling of \c errno are added.
describeErrnoCheckState(errno_modeling::ErrnoCheckState CS)67957014daSBalázs Kéri static const char *describeErrnoCheckState(errno_modeling::ErrnoCheckState CS) {
68957014daSBalázs Kéri   assert(CS == errno_modeling::MustNotBeChecked &&
69957014daSBalázs Kéri          "Errno description not applicable.");
70957014daSBalázs Kéri   return "may be undefined after the call and should not be used";
71957014daSBalázs Kéri }
72957014daSBalázs Kéri 
73bba497fbSArtem Dergachev namespace {
7494061df6SGabor Marton class StdLibraryFunctionsChecker
7594061df6SGabor Marton     : public Checker<check::PreCall, check::PostCall, eval::Call> {
7616506d78SGabor Marton 
7716506d78SGabor Marton   class Summary;
78bba497fbSArtem Dergachev 
79bba497fbSArtem Dergachev   /// Specify how much the analyzer engine should entrust modeling this function
80bba497fbSArtem Dergachev   /// to us. If he doesn't, he performs additional invalidations.
81f5086b38SGabor Marton   enum InvalidationKind { NoEvalCall, EvalCallAsPure };
82bba497fbSArtem Dergachev 
8347fec16cSArtem Dergachev   // The universal integral type to use in value range descriptions.
8447fec16cSArtem Dergachev   // Unsigned to make sure overflows are well-defined.
85f5086b38SGabor Marton   typedef uint64_t RangeInt;
8647fec16cSArtem Dergachev 
87bba497fbSArtem Dergachev   /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
88bba497fbSArtem Dergachev   /// a non-negative integer, which less than 5 and not equal to 2. For
89bba497fbSArtem Dergachev   /// `ComparesToArgument', holds information about how exactly to compare to
90bba497fbSArtem Dergachev   /// the argument.
91f5086b38SGabor Marton   typedef std::vector<std::pair<RangeInt, RangeInt>> IntRangeVector;
92bba497fbSArtem Dergachev 
93bba497fbSArtem Dergachev   /// A reference to an argument or return value by its number.
94bba497fbSArtem Dergachev   /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
95bba497fbSArtem Dergachev   /// obviously uint32_t should be enough for all practical purposes.
96f5086b38SGabor Marton   typedef uint32_t ArgNo;
97c6b8484eSGabor Marton   static const ArgNo Ret;
98bba497fbSArtem Dergachev 
99a7cb951fSGabor Marton   /// Returns the string representation of an argument index.
100a7cb951fSGabor Marton   /// E.g.: (1) -> '1st arg', (2) - > '2nd arg'
101a7cb951fSGabor Marton   static SmallString<8> getArgDesc(ArgNo);
102a7cb951fSGabor Marton 
10394061df6SGabor Marton   class ValueConstraint;
10494061df6SGabor Marton 
10594061df6SGabor Marton   // Pointer to the ValueConstraint. We need a copyable, polymorphic and
10694061df6SGabor Marton   // default initialize able type (vector needs that). A raw pointer was good,
10794061df6SGabor Marton   // however, we cannot default initialize that. unique_ptr makes the Summary
10894061df6SGabor Marton   // class non-copyable, therefore not an option. Releasing the copyability
10994061df6SGabor Marton   // requirement would render the initialization of the Summary map infeasible.
11094061df6SGabor Marton   using ValueConstraintPtr = std::shared_ptr<ValueConstraint>;
11194061df6SGabor Marton 
112c6b8484eSGabor Marton   /// Polymorphic base class that represents a constraint on a given argument
113c6b8484eSGabor Marton   /// (or return value) of a function. Derived classes implement different kind
114c6b8484eSGabor Marton   /// of constraints, e.g range constraints or correlation between two
115c6b8484eSGabor Marton   /// arguments.
116c6b8484eSGabor Marton   class ValueConstraint {
117c6b8484eSGabor Marton   public:
ValueConstraint(ArgNo ArgN)118c6b8484eSGabor Marton     ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {}
~ValueConstraint()119c6b8484eSGabor Marton     virtual ~ValueConstraint() {}
120c6b8484eSGabor Marton     /// Apply the effects of the constraint on the given program state. If null
121c6b8484eSGabor Marton     /// is returned then the constraint is not feasible.
122c6b8484eSGabor Marton     virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
123bd03ef19SGabor Marton                                   const Summary &Summary,
124bd03ef19SGabor Marton                                   CheckerContext &C) const = 0;
negate() const12594061df6SGabor Marton     virtual ValueConstraintPtr negate() const {
12694061df6SGabor Marton       llvm_unreachable("Not implemented");
12794061df6SGabor Marton     };
12816506d78SGabor Marton 
12916506d78SGabor Marton     // Check whether the constraint is malformed or not. It is malformed if the
13016506d78SGabor Marton     // specified argument has a mismatch with the given FunctionDecl (e.g. the
13116506d78SGabor Marton     // arg number is out-of-range of the function's argument list).
checkValidity(const FunctionDecl * FD) const13216506d78SGabor Marton     bool checkValidity(const FunctionDecl *FD) const {
13316506d78SGabor Marton       const bool ValidArg = ArgN == Ret || ArgN < FD->getNumParams();
13416506d78SGabor Marton       assert(ValidArg && "Arg out of range!");
13516506d78SGabor Marton       if (!ValidArg)
13616506d78SGabor Marton         return false;
13716506d78SGabor Marton       // Subclasses may further refine the validation.
13816506d78SGabor Marton       return checkSpecificValidity(FD);
13916506d78SGabor Marton     }
getArgNo() const140c6b8484eSGabor Marton     ArgNo getArgNo() const { return ArgN; }
141c6b8484eSGabor Marton 
1424b99f9c7SGabor Marton     // Return those arguments that should be tracked when we report a bug. By
1434b99f9c7SGabor Marton     // default it is the argument that is constrained, however, in some special
1444b99f9c7SGabor Marton     // cases we need to track other arguments as well. E.g. a buffer size might
1454b99f9c7SGabor Marton     // be encoded in another argument.
getArgsToTrack() const1464b99f9c7SGabor Marton     virtual std::vector<ArgNo> getArgsToTrack() const { return {ArgN}; }
1474b99f9c7SGabor Marton 
148a97648b9SGabor Marton     virtual StringRef getName() const = 0;
149a97648b9SGabor Marton 
150a7cb951fSGabor Marton     // Give a description that explains the constraint to the user. Used when
151a7cb951fSGabor Marton     // the bug is reported.
describe(ProgramStateRef State,const Summary & Summary) const152a7cb951fSGabor Marton     virtual std::string describe(ProgramStateRef State,
153a7cb951fSGabor Marton                                  const Summary &Summary) const {
154a7cb951fSGabor Marton       // There are some descendant classes that are not used as argument
155a7cb951fSGabor Marton       // constraints, e.g. ComparisonConstraint. In that case we can safely
156a7cb951fSGabor Marton       // ignore the implementation of this function.
157a7cb951fSGabor Marton       llvm_unreachable("Not implemented");
158a7cb951fSGabor Marton     }
159a7cb951fSGabor Marton 
160c6b8484eSGabor Marton   protected:
161c6b8484eSGabor Marton     ArgNo ArgN; // Argument to which we apply the constraint.
16216506d78SGabor Marton 
163d8e5a0c4SZarko Todorovski     /// Do polymorphic validation check on the constraint.
checkSpecificValidity(const FunctionDecl * FD) const16416506d78SGabor Marton     virtual bool checkSpecificValidity(const FunctionDecl *FD) const {
16516506d78SGabor Marton       return true;
16616506d78SGabor Marton     }
167c6b8484eSGabor Marton   };
168c6b8484eSGabor Marton 
169c6b8484eSGabor Marton   /// Given a range, should the argument stay inside or outside this range?
170c6b8484eSGabor Marton   enum RangeKind { OutOfRange, WithinRange };
171c6b8484eSGabor Marton 
172a787a4edSGabor Marton   /// Encapsulates a range on a single symbol.
173c6b8484eSGabor Marton   class RangeConstraint : public ValueConstraint {
174a787a4edSGabor Marton     RangeKind Kind;
175a787a4edSGabor Marton     // A range is formed as a set of intervals (sub-ranges).
176a787a4edSGabor Marton     // E.g. {['A', 'Z'], ['a', 'z']}
177a787a4edSGabor Marton     //
178a787a4edSGabor Marton     // The default constructed RangeConstraint has an empty range set, applying
179a787a4edSGabor Marton     // such constraint does not involve any assumptions, thus the State remains
180a787a4edSGabor Marton     // unchanged. This is meaningful, if the range is dependent on a looked up
181a787a4edSGabor Marton     // type (e.g. [0, Socklen_tMax]). If the type is not found, then the range
182a787a4edSGabor Marton     // is default initialized to be empty.
183a787a4edSGabor Marton     IntRangeVector Ranges;
184bba497fbSArtem Dergachev 
185bba497fbSArtem Dergachev   public:
getName() const186a97648b9SGabor Marton     StringRef getName() const override { return "Range"; }
RangeConstraint(ArgNo ArgN,RangeKind Kind,const IntRangeVector & Ranges)187a787a4edSGabor Marton     RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges)
188a787a4edSGabor Marton         : ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {}
189bba497fbSArtem Dergachev 
190a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
191a7cb951fSGabor Marton                          const Summary &Summary) const override;
192a7cb951fSGabor Marton 
getRanges() const193a787a4edSGabor Marton     const IntRangeVector &getRanges() const { return Ranges; }
194bba497fbSArtem Dergachev 
195bba497fbSArtem Dergachev   private:
196f5086b38SGabor Marton     ProgramStateRef applyAsOutOfRange(ProgramStateRef State,
197f5086b38SGabor Marton                                       const CallEvent &Call,
198f5086b38SGabor Marton                                       const Summary &Summary) const;
199f5086b38SGabor Marton     ProgramStateRef applyAsWithinRange(ProgramStateRef State,
200f5086b38SGabor Marton                                        const CallEvent &Call,
201f5086b38SGabor Marton                                        const Summary &Summary) const;
20225bbe234SZurab Tsinadze 
203bba497fbSArtem Dergachev   public:
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const204bba497fbSArtem Dergachev     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
205bd03ef19SGabor Marton                           const Summary &Summary,
206bd03ef19SGabor Marton                           CheckerContext &C) const override {
207bba497fbSArtem Dergachev       switch (Kind) {
208bba497fbSArtem Dergachev       case OutOfRange:
209bba497fbSArtem Dergachev         return applyAsOutOfRange(State, Call, Summary);
210bba497fbSArtem Dergachev       case WithinRange:
211bba497fbSArtem Dergachev         return applyAsWithinRange(State, Call, Summary);
212bba497fbSArtem Dergachev       }
213c6b8484eSGabor Marton       llvm_unreachable("Unknown range kind!");
214bba497fbSArtem Dergachev     }
21594061df6SGabor Marton 
negate() const21694061df6SGabor Marton     ValueConstraintPtr negate() const override {
21794061df6SGabor Marton       RangeConstraint Tmp(*this);
21894061df6SGabor Marton       switch (Kind) {
21994061df6SGabor Marton       case OutOfRange:
22094061df6SGabor Marton         Tmp.Kind = WithinRange;
22194061df6SGabor Marton         break;
22294061df6SGabor Marton       case WithinRange:
22394061df6SGabor Marton         Tmp.Kind = OutOfRange;
22494061df6SGabor Marton         break;
22594061df6SGabor Marton       }
22694061df6SGabor Marton       return std::make_shared<RangeConstraint>(Tmp);
22794061df6SGabor Marton     }
22816506d78SGabor Marton 
checkSpecificValidity(const FunctionDecl * FD) const22916506d78SGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
23016506d78SGabor Marton       const bool ValidArg =
23116506d78SGabor Marton           getArgType(FD, ArgN)->isIntegralType(FD->getASTContext());
23216506d78SGabor Marton       assert(ValidArg &&
23316506d78SGabor Marton              "This constraint should be applied on an integral type");
23416506d78SGabor Marton       return ValidArg;
23516506d78SGabor Marton     }
236bba497fbSArtem Dergachev   };
237bba497fbSArtem Dergachev 
238c6b8484eSGabor Marton   class ComparisonConstraint : public ValueConstraint {
239c6b8484eSGabor Marton     BinaryOperator::Opcode Opcode;
240c6b8484eSGabor Marton     ArgNo OtherArgN;
241c6b8484eSGabor Marton 
242c6b8484eSGabor Marton   public:
getName() const243*a210f404SKazu Hirata     StringRef getName() const override { return "Comparison"; };
ComparisonConstraint(ArgNo ArgN,BinaryOperator::Opcode Opcode,ArgNo OtherArgN)244c6b8484eSGabor Marton     ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode,
245c6b8484eSGabor Marton                          ArgNo OtherArgN)
246c6b8484eSGabor Marton         : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {}
getOtherArgNo() const247c6b8484eSGabor Marton     ArgNo getOtherArgNo() const { return OtherArgN; }
getOpcode() const248c6b8484eSGabor Marton     BinaryOperator::Opcode getOpcode() const { return Opcode; }
249c6b8484eSGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
250bd03ef19SGabor Marton                           const Summary &Summary,
251bd03ef19SGabor Marton                           CheckerContext &C) const override;
252c6b8484eSGabor Marton   };
253c6b8484eSGabor Marton 
254ededa65dSGabor Marton   class NotNullConstraint : public ValueConstraint {
255ededa65dSGabor Marton     using ValueConstraint::ValueConstraint;
256ededa65dSGabor Marton     // This variable has a role when we negate the constraint.
257ededa65dSGabor Marton     bool CannotBeNull = true;
258ededa65dSGabor Marton 
259ededa65dSGabor Marton   public:
260a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
261a7cb951fSGabor Marton                          const Summary &Summary) const override;
getName() const262a97648b9SGabor Marton     StringRef getName() const override { return "NonNull"; }
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const263ededa65dSGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
264bd03ef19SGabor Marton                           const Summary &Summary,
265bd03ef19SGabor Marton                           CheckerContext &C) const override {
266ededa65dSGabor Marton       SVal V = getArgSVal(Call, getArgNo());
267defd95efSVince Bridgers       if (V.isUndef())
268defd95efSVince Bridgers         return State;
269defd95efSVince Bridgers 
270ededa65dSGabor Marton       DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>();
27196ccb690SBalazs Benics       if (!isa<Loc>(L))
272ededa65dSGabor Marton         return State;
273ededa65dSGabor Marton 
274ededa65dSGabor Marton       return State->assume(L, CannotBeNull);
275ededa65dSGabor Marton     }
276ededa65dSGabor Marton 
negate() const277ededa65dSGabor Marton     ValueConstraintPtr negate() const override {
278ededa65dSGabor Marton       NotNullConstraint Tmp(*this);
279ededa65dSGabor Marton       Tmp.CannotBeNull = !this->CannotBeNull;
280ededa65dSGabor Marton       return std::make_shared<NotNullConstraint>(Tmp);
281ededa65dSGabor Marton     }
28216506d78SGabor Marton 
checkSpecificValidity(const FunctionDecl * FD) const28316506d78SGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
28416506d78SGabor Marton       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
28516506d78SGabor Marton       assert(ValidArg &&
28616506d78SGabor Marton              "This constraint should be applied only on a pointer type");
28716506d78SGabor Marton       return ValidArg;
28816506d78SGabor Marton     }
289ededa65dSGabor Marton   };
290ededa65dSGabor Marton 
291f0b9dbcfSGabor Marton   // Represents a buffer argument with an additional size constraint. The
292f0b9dbcfSGabor Marton   // constraint may be a concrete value, or a symbolic value in an argument.
293f0b9dbcfSGabor Marton   // Example 1. Concrete value as the minimum buffer size.
294f0b9dbcfSGabor Marton   //   char *asctime_r(const struct tm *restrict tm, char *restrict buf);
295f0b9dbcfSGabor Marton   //   // `buf` size must be at least 26 bytes according the POSIX standard.
296f0b9dbcfSGabor Marton   // Example 2. Argument as a buffer size.
297bd03ef19SGabor Marton   //   ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
298f0b9dbcfSGabor Marton   // Example 3. The size is computed as a multiplication of other args.
29941928c97SGabor Marton   //   size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
30041928c97SGabor Marton   //   // Here, ptr is the buffer, and its minimum size is `size * nmemb`.
301bd03ef19SGabor Marton   class BufferSizeConstraint : public ValueConstraint {
302f0b9dbcfSGabor Marton     // The concrete value which is the minimum size for the buffer.
303f0b9dbcfSGabor Marton     llvm::Optional<llvm::APSInt> ConcreteSize;
304bd03ef19SGabor Marton     // The argument which holds the size of the buffer.
305f0b9dbcfSGabor Marton     llvm::Optional<ArgNo> SizeArgN;
30641928c97SGabor Marton     // The argument which is a multiplier to size. This is set in case of
30741928c97SGabor Marton     // `fread` like functions where the size is computed as a multiplication of
30841928c97SGabor Marton     // two arguments.
30941928c97SGabor Marton     llvm::Optional<ArgNo> SizeMultiplierArgN;
310bd03ef19SGabor Marton     // The operator we use in apply. This is negated in negate().
311bd03ef19SGabor Marton     BinaryOperator::Opcode Op = BO_LE;
312bd03ef19SGabor Marton 
313bd03ef19SGabor Marton   public:
getName() const314a97648b9SGabor Marton     StringRef getName() const override { return "BufferSize"; }
BufferSizeConstraint(ArgNo Buffer,llvm::APSInt BufMinSize)315f0b9dbcfSGabor Marton     BufferSizeConstraint(ArgNo Buffer, llvm::APSInt BufMinSize)
316f0b9dbcfSGabor Marton         : ValueConstraint(Buffer), ConcreteSize(BufMinSize) {}
BufferSizeConstraint(ArgNo Buffer,ArgNo BufSize)317bd03ef19SGabor Marton     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize)
318bd03ef19SGabor Marton         : ValueConstraint(Buffer), SizeArgN(BufSize) {}
BufferSizeConstraint(ArgNo Buffer,ArgNo BufSize,ArgNo BufSizeMultiplier)31941928c97SGabor Marton     BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier)
32041928c97SGabor Marton         : ValueConstraint(Buffer), SizeArgN(BufSize),
32141928c97SGabor Marton           SizeMultiplierArgN(BufSizeMultiplier) {}
32241928c97SGabor Marton 
getArgsToTrack() const3234b99f9c7SGabor Marton     std::vector<ArgNo> getArgsToTrack() const override {
3244b99f9c7SGabor Marton       std::vector<ArgNo> Result{ArgN};
3254b99f9c7SGabor Marton       if (SizeArgN)
3264b99f9c7SGabor Marton         Result.push_back(*SizeArgN);
3274b99f9c7SGabor Marton       if (SizeMultiplierArgN)
3284b99f9c7SGabor Marton         Result.push_back(*SizeMultiplierArgN);
3294b99f9c7SGabor Marton       return Result;
3304b99f9c7SGabor Marton     }
3314b99f9c7SGabor Marton 
332a7cb951fSGabor Marton     std::string describe(ProgramStateRef State,
333a7cb951fSGabor Marton                          const Summary &Summary) const override;
334a7cb951fSGabor Marton 
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const335bd03ef19SGabor Marton     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
336bd03ef19SGabor Marton                           const Summary &Summary,
337bd03ef19SGabor Marton                           CheckerContext &C) const override {
33841928c97SGabor Marton       SValBuilder &SvalBuilder = C.getSValBuilder();
339bd03ef19SGabor Marton       // The buffer argument.
340bd03ef19SGabor Marton       SVal BufV = getArgSVal(Call, getArgNo());
341f0b9dbcfSGabor Marton 
342f0b9dbcfSGabor Marton       // Get the size constraint.
343f0b9dbcfSGabor Marton       const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() {
344f0b9dbcfSGabor Marton         if (ConcreteSize) {
345f0b9dbcfSGabor Marton           return SVal(SvalBuilder.makeIntVal(*ConcreteSize));
346a7cb951fSGabor Marton         }
347a7cb951fSGabor Marton         assert(SizeArgN && "The constraint must be either a concrete value or "
348a7cb951fSGabor Marton                            "encoded in an argument.");
349bd03ef19SGabor Marton         // The size argument.
350f0b9dbcfSGabor Marton         SVal SizeV = getArgSVal(Call, *SizeArgN);
35141928c97SGabor Marton         // Multiply with another argument if given.
35241928c97SGabor Marton         if (SizeMultiplierArgN) {
35341928c97SGabor Marton           SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
35441928c97SGabor Marton           SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
355f0b9dbcfSGabor Marton                                         Summary.getArgType(*SizeArgN));
35641928c97SGabor Marton         }
357f0b9dbcfSGabor Marton         return SizeV;
358f0b9dbcfSGabor Marton       }();
359f0b9dbcfSGabor Marton 
360bd03ef19SGabor Marton       // The dynamic size of the buffer argument, got from the analyzer engine.
3619b3df78bSCharusso       SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
362bd03ef19SGabor Marton 
363bd03ef19SGabor Marton       SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize,
364bd03ef19SGabor Marton                                             SvalBuilder.getContext().BoolTy);
365bd03ef19SGabor Marton       if (auto F = Feasible.getAs<DefinedOrUnknownSVal>())
366bd03ef19SGabor Marton         return State->assume(*F, true);
367bd03ef19SGabor Marton 
368bd03ef19SGabor Marton       // We can get here only if the size argument or the dynamic size is
369bd03ef19SGabor Marton       // undefined. But the dynamic size should never be undefined, only
370bd03ef19SGabor Marton       // unknown. So, here, the size of the argument is undefined, i.e. we
371bd03ef19SGabor Marton       // cannot apply the constraint. Actually, other checkers like
372bd03ef19SGabor Marton       // CallAndMessage should catch this situation earlier, because we call a
373bd03ef19SGabor Marton       // function with an uninitialized argument.
374bd03ef19SGabor Marton       llvm_unreachable("Size argument or the dynamic size is Undefined");
375bd03ef19SGabor Marton     }
376bd03ef19SGabor Marton 
negate() const377bd03ef19SGabor Marton     ValueConstraintPtr negate() const override {
378bd03ef19SGabor Marton       BufferSizeConstraint Tmp(*this);
379bd03ef19SGabor Marton       Tmp.Op = BinaryOperator::negateComparisonOp(Op);
380bd03ef19SGabor Marton       return std::make_shared<BufferSizeConstraint>(Tmp);
381bd03ef19SGabor Marton     }
3823ff220deSGabor Marton 
checkSpecificValidity(const FunctionDecl * FD) const3833ff220deSGabor Marton     bool checkSpecificValidity(const FunctionDecl *FD) const override {
3843ff220deSGabor Marton       const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
3853ff220deSGabor Marton       assert(ValidArg &&
3863ff220deSGabor Marton              "This constraint should be applied only on a pointer type");
3873ff220deSGabor Marton       return ValidArg;
3883ff220deSGabor Marton     }
389bd03ef19SGabor Marton   };
390bd03ef19SGabor Marton 
391c6b8484eSGabor Marton   /// The complete list of constraints that defines a single branch.
392f68c0a2fSArtem Dergachev   using ConstraintSet = std::vector<ValueConstraintPtr>;
393f68c0a2fSArtem Dergachev 
394957014daSBalázs Kéri   /// Define how a function affects the system variable 'errno'.
395957014daSBalázs Kéri   /// This works together with the ErrnoModeling and ErrnoChecker classes.
396957014daSBalázs Kéri   class ErrnoConstraintBase {
397957014daSBalázs Kéri   public:
398957014daSBalázs Kéri     /// Apply specific state changes related to the errno variable.
399957014daSBalázs Kéri     virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
400957014daSBalázs Kéri                                   const Summary &Summary,
401957014daSBalázs Kéri                                   CheckerContext &C) const = 0;
402957014daSBalázs Kéri     /// Get a description about what is applied to 'errno' and how is it allowed
403957014daSBalázs Kéri     /// to be used. If ErrnoChecker generates a bug then this message is
404957014daSBalázs Kéri     /// displayed as a note at the function call.
405957014daSBalázs Kéri     /// It may return empty string if no note tag is to be added.
describe(StringRef FunctionName) const406957014daSBalázs Kéri     virtual std::string describe(StringRef FunctionName) const { return ""; }
407957014daSBalázs Kéri 
~ErrnoConstraintBase()408957014daSBalázs Kéri     virtual ~ErrnoConstraintBase() {}
409957014daSBalázs Kéri 
410957014daSBalázs Kéri   protected:
411957014daSBalázs Kéri     /// Many of the descendant classes use this value.
412957014daSBalázs Kéri     const errno_modeling::ErrnoCheckState CheckState;
413957014daSBalázs Kéri 
ErrnoConstraintBase(errno_modeling::ErrnoCheckState CS)414957014daSBalázs Kéri     ErrnoConstraintBase(errno_modeling::ErrnoCheckState CS) : CheckState(CS) {}
415957014daSBalázs Kéri 
416957014daSBalázs Kéri     /// This is used for conjure symbol for errno to differentiate from the
417957014daSBalázs Kéri     /// original call expression (same expression is used for the errno symbol).
418957014daSBalázs Kéri     static int Tag;
419957014daSBalázs Kéri   };
420957014daSBalázs Kéri 
421957014daSBalázs Kéri   /// Set value of 'errno' to be related to 0 in a specified way, with a
422957014daSBalázs Kéri   /// specified "errno check state". For example with \c BO_GT 'errno' is
423957014daSBalázs Kéri   /// constrained to be greater than 0. Use this for failure cases of functions.
424957014daSBalázs Kéri   class ZeroRelatedErrnoConstraint : public ErrnoConstraintBase {
425957014daSBalázs Kéri     BinaryOperatorKind Op;
426957014daSBalázs Kéri 
427957014daSBalázs Kéri   public:
ZeroRelatedErrnoConstraint(clang::BinaryOperatorKind OpK,errno_modeling::ErrnoCheckState CS)428957014daSBalázs Kéri     ZeroRelatedErrnoConstraint(clang::BinaryOperatorKind OpK,
429957014daSBalázs Kéri                                errno_modeling::ErrnoCheckState CS)
430957014daSBalázs Kéri         : ErrnoConstraintBase(CS), Op(OpK) {
431957014daSBalázs Kéri       assert(BinaryOperator::isComparisonOp(OpK));
432957014daSBalázs Kéri     }
433957014daSBalázs Kéri 
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const434957014daSBalázs Kéri     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
435957014daSBalázs Kéri                           const Summary &Summary,
436957014daSBalázs Kéri                           CheckerContext &C) const override {
437957014daSBalázs Kéri       SValBuilder &SVB = C.getSValBuilder();
438957014daSBalázs Kéri       NonLoc ErrnoSVal =
439957014daSBalázs Kéri           SVB.conjureSymbolVal(&Tag, Call.getOriginExpr(),
440957014daSBalázs Kéri                                C.getLocationContext(), C.getASTContext().IntTy,
441957014daSBalázs Kéri                                C.blockCount())
442957014daSBalázs Kéri               .castAs<NonLoc>();
443957014daSBalázs Kéri       NonLoc ZeroVal =
444957014daSBalázs Kéri           SVB.makeZeroVal(C.getASTContext().IntTy).castAs<NonLoc>();
445957014daSBalázs Kéri       DefinedOrUnknownSVal Cond =
446957014daSBalázs Kéri           SVB.evalBinOp(State, Op, ErrnoSVal, ZeroVal, SVB.getConditionType())
447957014daSBalázs Kéri               .castAs<DefinedOrUnknownSVal>();
448957014daSBalázs Kéri       State = State->assume(Cond, true);
449957014daSBalázs Kéri       if (!State)
450957014daSBalázs Kéri         return State;
451957014daSBalázs Kéri       return errno_modeling::setErrnoValue(State, C.getLocationContext(),
452957014daSBalázs Kéri                                            ErrnoSVal, CheckState);
453957014daSBalázs Kéri     }
454957014daSBalázs Kéri 
describe(StringRef FunctionName) const455957014daSBalázs Kéri     std::string describe(StringRef FunctionName) const override {
456957014daSBalázs Kéri       if (CheckState == errno_modeling::Irrelevant)
457957014daSBalázs Kéri         return "";
458957014daSBalázs Kéri       return (Twine("Assuming that function '") + FunctionName.str() +
459957014daSBalázs Kéri               "' fails, in this case the value 'errno' becomes " +
460957014daSBalázs Kéri               BinaryOperator::getOpcodeStr(Op).str() + " 0 and " +
461957014daSBalázs Kéri               describeErrnoCheckState(CheckState))
462957014daSBalázs Kéri           .str();
463957014daSBalázs Kéri     }
464957014daSBalázs Kéri   };
465957014daSBalázs Kéri 
466957014daSBalázs Kéri   /// Applies the constraints to 'errno' for a common case when a standard
467957014daSBalázs Kéri   /// function is successful. The value of 'errno' after the call is not
468957014daSBalázs Kéri   /// specified by the standard (it may change or not). The \c ErrnoChecker can
469957014daSBalázs Kéri   /// generate a bug if 'errno' is read afterwards.
470957014daSBalázs Kéri   class SuccessErrnoConstraint : public ErrnoConstraintBase {
471957014daSBalázs Kéri   public:
SuccessErrnoConstraint()472957014daSBalázs Kéri     SuccessErrnoConstraint()
473957014daSBalázs Kéri         : ErrnoConstraintBase(errno_modeling::MustNotBeChecked) {}
474957014daSBalázs Kéri 
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const475957014daSBalázs Kéri     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
476957014daSBalázs Kéri                           const Summary &Summary,
477957014daSBalázs Kéri                           CheckerContext &C) const override {
478957014daSBalázs Kéri       return errno_modeling::setErrnoState(State, CheckState);
479957014daSBalázs Kéri     }
480957014daSBalázs Kéri 
describe(StringRef FunctionName) const481957014daSBalázs Kéri     std::string describe(StringRef FunctionName) const override {
482957014daSBalázs Kéri       return (Twine("Assuming that function '") + FunctionName.str() +
483957014daSBalázs Kéri               "' is successful, in this case the value 'errno' " +
484957014daSBalázs Kéri               describeErrnoCheckState(CheckState))
485957014daSBalázs Kéri           .str();
486957014daSBalázs Kéri     }
487957014daSBalázs Kéri   };
488957014daSBalázs Kéri 
489957014daSBalázs Kéri   /// Set errno constraints if use of 'errno' is completely irrelevant to the
490957014daSBalázs Kéri   /// modeled function or modeling is not possible.
491957014daSBalázs Kéri   class NoErrnoConstraint : public ErrnoConstraintBase {
492957014daSBalázs Kéri   public:
NoErrnoConstraint()493957014daSBalázs Kéri     NoErrnoConstraint() : ErrnoConstraintBase(errno_modeling::Irrelevant) {}
494957014daSBalázs Kéri 
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const495957014daSBalázs Kéri     ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
496957014daSBalázs Kéri                           const Summary &Summary,
497957014daSBalázs Kéri                           CheckerContext &C) const override {
498957014daSBalázs Kéri       return errno_modeling::setErrnoState(State, CheckState);
499957014daSBalázs Kéri     }
500957014daSBalázs Kéri   };
501957014daSBalázs Kéri 
502f68c0a2fSArtem Dergachev   /// A single branch of a function summary.
503f68c0a2fSArtem Dergachev   ///
504f68c0a2fSArtem Dergachev   /// A branch is defined by a series of constraints - "assumptions" -
505f68c0a2fSArtem Dergachev   /// that together form a single possible outcome of invoking the function.
506f68c0a2fSArtem Dergachev   /// When static analyzer considers a branch, it tries to introduce
507f68c0a2fSArtem Dergachev   /// a child node in the Exploded Graph. The child node has to include
508f68c0a2fSArtem Dergachev   /// constraints that define the branch. If the constraints contradict
509f68c0a2fSArtem Dergachev   /// existing constraints in the state, the node is not created and the branch
510f68c0a2fSArtem Dergachev   /// is dropped; otherwise it's queued for future exploration.
511f68c0a2fSArtem Dergachev   /// The branch is accompanied by a note text that may be displayed
512f68c0a2fSArtem Dergachev   /// to the user when a bug is found on a path that takes this branch.
513f68c0a2fSArtem Dergachev   ///
514f68c0a2fSArtem Dergachev   /// For example, consider the branches in `isalpha(x)`:
515f68c0a2fSArtem Dergachev   ///   Branch 1)
516f68c0a2fSArtem Dergachev   ///     x is in range ['A', 'Z'] or in ['a', 'z']
517f68c0a2fSArtem Dergachev   ///     then the return value is not 0. (I.e. out-of-range [0, 0])
518f68c0a2fSArtem Dergachev   ///     and the note may say "Assuming the character is alphabetical"
519f68c0a2fSArtem Dergachev   ///   Branch 2)
520f68c0a2fSArtem Dergachev   ///     x is out-of-range ['A', 'Z'] and out-of-range ['a', 'z']
521f68c0a2fSArtem Dergachev   ///     then the return value is 0
522f68c0a2fSArtem Dergachev   ///     and the note may say "Assuming the character is non-alphabetical".
523f68c0a2fSArtem Dergachev   class SummaryCase {
524f68c0a2fSArtem Dergachev     ConstraintSet Constraints;
525957014daSBalázs Kéri     const ErrnoConstraintBase &ErrnoConstraint;
526f68c0a2fSArtem Dergachev     StringRef Note;
527f68c0a2fSArtem Dergachev 
528f68c0a2fSArtem Dergachev   public:
SummaryCase(ConstraintSet && Constraints,const ErrnoConstraintBase & ErrnoC,StringRef Note)529957014daSBalázs Kéri     SummaryCase(ConstraintSet &&Constraints, const ErrnoConstraintBase &ErrnoC,
530957014daSBalázs Kéri                 StringRef Note)
531957014daSBalázs Kéri         : Constraints(std::move(Constraints)), ErrnoConstraint(ErrnoC),
532957014daSBalázs Kéri           Note(Note) {}
533f68c0a2fSArtem Dergachev 
SummaryCase(const ConstraintSet & Constraints,const ErrnoConstraintBase & ErrnoC,StringRef Note)534957014daSBalázs Kéri     SummaryCase(const ConstraintSet &Constraints,
535957014daSBalázs Kéri                 const ErrnoConstraintBase &ErrnoC, StringRef Note)
536957014daSBalázs Kéri         : Constraints(Constraints), ErrnoConstraint(ErrnoC), Note(Note) {}
537f68c0a2fSArtem Dergachev 
getConstraints() const538f68c0a2fSArtem Dergachev     const ConstraintSet &getConstraints() const { return Constraints; }
getErrnoConstraint() const539957014daSBalázs Kéri     const ErrnoConstraintBase &getErrnoConstraint() const {
540957014daSBalázs Kéri       return ErrnoConstraint;
541957014daSBalázs Kéri     }
getNote() const542f68c0a2fSArtem Dergachev     StringRef getNote() const { return Note; }
543f68c0a2fSArtem Dergachev   };
544bba497fbSArtem Dergachev 
545a787a4edSGabor Marton   using ArgTypes = std::vector<Optional<QualType>>;
546a787a4edSGabor Marton   using RetType = Optional<QualType>;
54716506d78SGabor Marton 
54816506d78SGabor Marton   // A placeholder type, we use it whenever we do not care about the concrete
54916506d78SGabor Marton   // type in a Signature.
55016506d78SGabor Marton   const QualType Irrelevant{};
isIrrelevant(QualType T)55116506d78SGabor Marton   bool static isIrrelevant(QualType T) { return T.isNull(); }
55216506d78SGabor Marton 
55316506d78SGabor Marton   // The signature of a function we want to describe with a summary. This is a
55416506d78SGabor Marton   // concessive signature, meaning there may be irrelevant types in the
55516506d78SGabor Marton   // signature which we do not check against a function with concrete types.
556a787a4edSGabor Marton   // All types in the spec need to be canonical.
557a787a4edSGabor Marton   class Signature {
558a787a4edSGabor Marton     using ArgQualTypes = std::vector<QualType>;
559a787a4edSGabor Marton     ArgQualTypes ArgTys;
5603ff220deSGabor Marton     QualType RetTy;
561a787a4edSGabor Marton     // True if any component type is not found by lookup.
562a787a4edSGabor Marton     bool Invalid = false;
563a787a4edSGabor Marton 
564a787a4edSGabor Marton   public:
565a787a4edSGabor Marton     // Construct a signature from optional types. If any of the optional types
566a787a4edSGabor Marton     // are not set then the signature will be invalid.
Signature(ArgTypes ArgTys,RetType RetTy)567a787a4edSGabor Marton     Signature(ArgTypes ArgTys, RetType RetTy) {
568a787a4edSGabor Marton       for (Optional<QualType> Arg : ArgTys) {
569a787a4edSGabor Marton         if (!Arg) {
570a787a4edSGabor Marton           Invalid = true;
571a787a4edSGabor Marton           return;
572a787a4edSGabor Marton         } else {
573a787a4edSGabor Marton           assertArgTypeSuitableForSignature(*Arg);
574a787a4edSGabor Marton           this->ArgTys.push_back(*Arg);
575a787a4edSGabor Marton         }
576a787a4edSGabor Marton       }
577a787a4edSGabor Marton       if (!RetTy) {
578a787a4edSGabor Marton         Invalid = true;
579a787a4edSGabor Marton         return;
580a787a4edSGabor Marton       } else {
581a787a4edSGabor Marton         assertRetTypeSuitableForSignature(*RetTy);
582a787a4edSGabor Marton         this->RetTy = *RetTy;
58316506d78SGabor Marton       }
58416506d78SGabor Marton     }
5853ff220deSGabor Marton 
isInvalid() const586a787a4edSGabor Marton     bool isInvalid() const { return Invalid; }
58716506d78SGabor Marton     bool matches(const FunctionDecl *FD) const;
58816506d78SGabor Marton 
58916506d78SGabor Marton   private:
assertArgTypeSuitableForSignature(QualType T)59016506d78SGabor Marton     static void assertArgTypeSuitableForSignature(QualType T) {
59116506d78SGabor Marton       assert((T.isNull() || !T->isVoidType()) &&
59216506d78SGabor Marton              "We should have no void types in the spec");
59316506d78SGabor Marton       assert((T.isNull() || T.isCanonical()) &&
59416506d78SGabor Marton              "We should only have canonical types in the spec");
59516506d78SGabor Marton     }
assertRetTypeSuitableForSignature(QualType T)59616506d78SGabor Marton     static void assertRetTypeSuitableForSignature(QualType T) {
59716506d78SGabor Marton       assert((T.isNull() || T.isCanonical()) &&
59816506d78SGabor Marton              "We should only have canonical types in the spec");
59916506d78SGabor Marton     }
60016506d78SGabor Marton   };
60116506d78SGabor Marton 
getArgType(const FunctionDecl * FD,ArgNo ArgN)60216506d78SGabor Marton   static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) {
60316506d78SGabor Marton     assert(FD && "Function must be set");
60416506d78SGabor Marton     QualType T = (ArgN == Ret)
60516506d78SGabor Marton                      ? FD->getReturnType().getCanonicalType()
60616506d78SGabor Marton                      : FD->getParamDecl(ArgN)->getType().getCanonicalType();
60716506d78SGabor Marton     return T;
60816506d78SGabor Marton   }
60916506d78SGabor Marton 
610f68c0a2fSArtem Dergachev   using SummaryCases = std::vector<SummaryCase>;
611f5086b38SGabor Marton 
61216506d78SGabor Marton   /// A summary includes information about
61316506d78SGabor Marton   ///   * function prototype (signature)
61494061df6SGabor Marton   ///   * approach to invalidation,
615f68c0a2fSArtem Dergachev   ///   * a list of branches - so, a list of list of ranges,
61694061df6SGabor Marton   ///   * a list of argument constraints, that must be true on every branch.
61794061df6SGabor Marton   ///     If these constraints are not satisfied that means a fatal error
61894061df6SGabor Marton   ///     usually resulting in undefined behaviour.
61916506d78SGabor Marton   ///
62016506d78SGabor Marton   /// Application of a summary:
62116506d78SGabor Marton   ///   The signature and argument constraints together contain information
62216506d78SGabor Marton   ///   about which functions are handled by the summary. The signature can use
62316506d78SGabor Marton   ///   "wildcards", i.e. Irrelevant types. Irrelevant type of a parameter in
62416506d78SGabor Marton   ///   a signature means that type is not compared to the type of the parameter
62516506d78SGabor Marton   ///   in the found FunctionDecl. Argument constraints may specify additional
62616506d78SGabor Marton   ///   rules for the given parameter's type, those rules are checked once the
62716506d78SGabor Marton   ///   signature is matched.
62816506d78SGabor Marton   class Summary {
629f5086b38SGabor Marton     const InvalidationKind InvalidationKd;
630f68c0a2fSArtem Dergachev     SummaryCases Cases;
631c6b8484eSGabor Marton     ConstraintSet ArgConstraints;
632f5086b38SGabor Marton 
63316506d78SGabor Marton     // The function to which the summary applies. This is set after lookup and
63416506d78SGabor Marton     // match to the signature.
63516506d78SGabor Marton     const FunctionDecl *FD = nullptr;
63616506d78SGabor Marton 
63716506d78SGabor Marton   public:
Summary(InvalidationKind InvalidationKd)6383ff220deSGabor Marton     Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {}
6393ff220deSGabor Marton 
Case(ConstraintSet && CS,const ErrnoConstraintBase & ErrnoC,StringRef Note="")640957014daSBalázs Kéri     Summary &Case(ConstraintSet &&CS, const ErrnoConstraintBase &ErrnoC,
641957014daSBalázs Kéri                   StringRef Note = "") {
642957014daSBalázs Kéri       Cases.push_back(SummaryCase(std::move(CS), ErrnoC, Note));
643f5086b38SGabor Marton       return *this;
644f5086b38SGabor Marton     }
Case(const ConstraintSet & CS,const ErrnoConstraintBase & ErrnoC,StringRef Note="")645957014daSBalázs Kéri     Summary &Case(const ConstraintSet &CS, const ErrnoConstraintBase &ErrnoC,
646957014daSBalázs Kéri                   StringRef Note = "") {
647957014daSBalázs Kéri       Cases.push_back(SummaryCase(CS, ErrnoC, Note));
648b40b3196SGabor Marton       return *this;
649b40b3196SGabor Marton     }
ArgConstraint(ValueConstraintPtr VC)65094061df6SGabor Marton     Summary &ArgConstraint(ValueConstraintPtr VC) {
651a97648b9SGabor Marton       assert(VC->getArgNo() != Ret &&
652a97648b9SGabor Marton              "Arg constraint should not refer to the return value");
65394061df6SGabor Marton       ArgConstraints.push_back(VC);
65494061df6SGabor Marton       return *this;
65594061df6SGabor Marton     }
656bba497fbSArtem Dergachev 
getInvalidationKd() const65716506d78SGabor Marton     InvalidationKind getInvalidationKd() const { return InvalidationKd; }
getCases() const658f68c0a2fSArtem Dergachev     const SummaryCases &getCases() const { return Cases; }
getArgConstraints() const65916506d78SGabor Marton     const ConstraintSet &getArgConstraints() const { return ArgConstraints; }
660bba497fbSArtem Dergachev 
getArgType(ArgNo ArgN) const661f5086b38SGabor Marton     QualType getArgType(ArgNo ArgN) const {
66216506d78SGabor Marton       return StdLibraryFunctionsChecker::getArgType(FD, ArgN);
663bba497fbSArtem Dergachev     }
664bba497fbSArtem Dergachev 
66516506d78SGabor Marton     // Returns true if the summary should be applied to the given function.
66616506d78SGabor Marton     // And if yes then store the function declaration.
matchesAndSet(const Signature & Sign,const FunctionDecl * FD)66711d2e63aSGabor Marton     bool matchesAndSet(const Signature &Sign, const FunctionDecl *FD) {
66811d2e63aSGabor Marton       bool Result = Sign.matches(FD) && validateByConstraints(FD);
66916506d78SGabor Marton       if (Result) {
67016506d78SGabor Marton         assert(!this->FD && "FD must not be set more than once");
67116506d78SGabor Marton         this->FD = FD;
67216506d78SGabor Marton       }
67316506d78SGabor Marton       return Result;
67416506d78SGabor Marton     }
67516506d78SGabor Marton 
67616506d78SGabor Marton   private:
677d8e5a0c4SZarko Todorovski     // Once we know the exact type of the function then do validation check on
678d8e5a0c4SZarko Todorovski     // all the given constraints.
validateByConstraints(const FunctionDecl * FD) const67916506d78SGabor Marton     bool validateByConstraints(const FunctionDecl *FD) const {
680f68c0a2fSArtem Dergachev       for (const SummaryCase &Case : Cases)
681f68c0a2fSArtem Dergachev         for (const ValueConstraintPtr &Constraint : Case.getConstraints())
68216506d78SGabor Marton           if (!Constraint->checkValidity(FD))
68316506d78SGabor Marton             return false;
68416506d78SGabor Marton       for (const ValueConstraintPtr &Constraint : ArgConstraints)
68516506d78SGabor Marton         if (!Constraint->checkValidity(FD))
68616506d78SGabor Marton           return false;
68716506d78SGabor Marton       return true;
68816506d78SGabor Marton     }
689bba497fbSArtem Dergachev   };
690bba497fbSArtem Dergachev 
691bba497fbSArtem Dergachev   // The map of all functions supported by the checker. It is initialized
692bba497fbSArtem Dergachev   // lazily, and it doesn't change after initialization.
69362e747f6SGabor Marton   using FunctionSummaryMapType = llvm::DenseMap<const FunctionDecl *, Summary>;
69462e747f6SGabor Marton   mutable FunctionSummaryMapType FunctionSummaryMap;
695bba497fbSArtem Dergachev 
69694061df6SGabor Marton   mutable std::unique_ptr<BugType> BT_InvalidArg;
697c7635040SValeriy Savchenko   mutable bool SummariesInitialized = false;
69894061df6SGabor Marton 
getArgSVal(const CallEvent & Call,ArgNo ArgN)699f5086b38SGabor Marton   static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) {
700f5086b38SGabor Marton     return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN);
701bba497fbSArtem Dergachev   }
702bba497fbSArtem Dergachev 
703bba497fbSArtem Dergachev public:
70494061df6SGabor Marton   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
705bba497fbSArtem Dergachev   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
70644820630SArtem Dergachev   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
707bba497fbSArtem Dergachev 
7081525232eSGabor Marton   enum CheckKind {
7091525232eSGabor Marton     CK_StdCLibraryFunctionArgsChecker,
7101525232eSGabor Marton     CK_StdCLibraryFunctionsTesterChecker,
7111525232eSGabor Marton     CK_NumCheckKinds
7121525232eSGabor Marton   };
7135114db93SVince Bridgers   bool ChecksEnabled[CK_NumCheckKinds] = {false};
71494061df6SGabor Marton   CheckerNameRef CheckNames[CK_NumCheckKinds];
71594061df6SGabor Marton 
716ff4492c8SGabor Marton   bool DisplayLoadedSummaries = false;
717db4d5f70SGabor Marton   bool ModelPOSIX = false;
718edde4efcSBalazs Benics   bool ShouldAssumeControlledEnvironment = false;
719ff4492c8SGabor Marton 
720bba497fbSArtem Dergachev private:
721f5086b38SGabor Marton   Optional<Summary> findFunctionSummary(const FunctionDecl *FD,
722bba497fbSArtem Dergachev                                         CheckerContext &C) const;
72394061df6SGabor Marton   Optional<Summary> findFunctionSummary(const CallEvent &Call,
72494061df6SGabor Marton                                         CheckerContext &C) const;
725bba497fbSArtem Dergachev 
726536456a7SGabor Marton   void initFunctionSummaries(CheckerContext &C) const;
72794061df6SGabor Marton 
reportBug(const CallEvent & Call,ExplodedNode * N,const ValueConstraint * VC,const Summary & Summary,CheckerContext & C) const72894061df6SGabor Marton   void reportBug(const CallEvent &Call, ExplodedNode *N,
729a7cb951fSGabor Marton                  const ValueConstraint *VC, const Summary &Summary,
730a7cb951fSGabor Marton                  CheckerContext &C) const {
73194061df6SGabor Marton     if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
73294061df6SGabor Marton       return;
733a97648b9SGabor Marton     std::string Msg =
734a97648b9SGabor Marton         (Twine("Function argument constraint is not satisfied, constraint: ") +
735a7cb951fSGabor Marton          VC->getName().data())
736a97648b9SGabor Marton             .str();
73794061df6SGabor Marton     if (!BT_InvalidArg)
73894061df6SGabor Marton       BT_InvalidArg = std::make_unique<BugType>(
73994061df6SGabor Marton           CheckNames[CK_StdCLibraryFunctionArgsChecker],
74094061df6SGabor Marton           "Unsatisfied argument constraints", categories::LogicError);
74194061df6SGabor Marton     auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
7424b99f9c7SGabor Marton 
7434b99f9c7SGabor Marton     for (ArgNo ArgN : VC->getArgsToTrack())
7444b99f9c7SGabor Marton       bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
745a97648b9SGabor Marton 
746a97648b9SGabor Marton     // Highlight the range of the argument that was violated.
747a97648b9SGabor Marton     R->addRange(Call.getArgSourceRange(VC->getArgNo()));
748a97648b9SGabor Marton 
749a7cb951fSGabor Marton     // Describe the argument constraint in a note.
750a7cb951fSGabor Marton     R->addNote(VC->describe(C.getState(), Summary), R->getLocation(),
751a7cb951fSGabor Marton                Call.getArgSourceRange(VC->getArgNo()));
752a7cb951fSGabor Marton 
75394061df6SGabor Marton     C.emitReport(std::move(R));
75494061df6SGabor Marton   }
755957014daSBalázs Kéri 
756957014daSBalázs Kéri   /// These are the errno constraints that can be passed to summary cases.
757957014daSBalázs Kéri   /// One of these should fit for a single summary case.
758957014daSBalázs Kéri   /// Usually if a failure return value exists for function, that function
759957014daSBalázs Kéri   /// needs different cases for success and failure with different errno
760957014daSBalázs Kéri   /// constraints (and different return value constraints).
761957014daSBalázs Kéri   const NoErrnoConstraint ErrnoIrrelevant;
762957014daSBalázs Kéri   const SuccessErrnoConstraint ErrnoMustNotBeChecked;
763957014daSBalázs Kéri   const ZeroRelatedErrnoConstraint ErrnoNEZeroIrrelevant{
764957014daSBalázs Kéri       clang::BinaryOperatorKind::BO_NE, errno_modeling::Irrelevant};
765bba497fbSArtem Dergachev };
766c6b8484eSGabor Marton 
767957014daSBalázs Kéri int StdLibraryFunctionsChecker::ErrnoConstraintBase::Tag = 0;
768957014daSBalázs Kéri 
769c6b8484eSGabor Marton const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret =
770c6b8484eSGabor Marton     std::numeric_limits<ArgNo>::max();
771c6b8484eSGabor Marton 
772bba497fbSArtem Dergachev } // end of anonymous namespace
773bba497fbSArtem Dergachev 
getBVF(ProgramStateRef State)774a7cb951fSGabor Marton static BasicValueFactory &getBVF(ProgramStateRef State) {
775a7cb951fSGabor Marton   ProgramStateManager &Mgr = State->getStateManager();
776a7cb951fSGabor Marton   SValBuilder &SVB = Mgr.getSValBuilder();
777a7cb951fSGabor Marton   return SVB.getBasicValueFactory();
778a7cb951fSGabor Marton }
779a7cb951fSGabor Marton 
describe(ProgramStateRef State,const Summary & Summary) const780a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::NotNullConstraint::describe(
781a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
782a7cb951fSGabor Marton   SmallString<48> Result;
783a7cb951fSGabor Marton   Result += "The ";
784a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
785a7cb951fSGabor Marton   Result += " should not be NULL";
786a7cb951fSGabor Marton   return Result.c_str();
787a7cb951fSGabor Marton }
788a7cb951fSGabor Marton 
describe(ProgramStateRef State,const Summary & Summary) const789a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::RangeConstraint::describe(
790a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
791a7cb951fSGabor Marton 
792a7cb951fSGabor Marton   BasicValueFactory &BVF = getBVF(State);
793a7cb951fSGabor Marton 
794a7cb951fSGabor Marton   QualType T = Summary.getArgType(getArgNo());
795a7cb951fSGabor Marton   SmallString<48> Result;
796a7cb951fSGabor Marton   Result += "The ";
797a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
798a7cb951fSGabor Marton   Result += " should be ";
799a7cb951fSGabor Marton 
800a7cb951fSGabor Marton   // Range kind as a string.
801a7cb951fSGabor Marton   Kind == OutOfRange ? Result += "out of" : Result += "within";
802a7cb951fSGabor Marton 
803a7cb951fSGabor Marton   // Get the range values as a string.
804a7cb951fSGabor Marton   Result += " the range ";
805a7cb951fSGabor Marton   if (Ranges.size() > 1)
806a7cb951fSGabor Marton     Result += "[";
807a7cb951fSGabor Marton   unsigned I = Ranges.size();
808a7cb951fSGabor Marton   for (const std::pair<RangeInt, RangeInt> &R : Ranges) {
809a7cb951fSGabor Marton     Result += "[";
810a7cb951fSGabor Marton     const llvm::APSInt &Min = BVF.getValue(R.first, T);
811a7cb951fSGabor Marton     const llvm::APSInt &Max = BVF.getValue(R.second, T);
812a7cb951fSGabor Marton     Min.toString(Result);
813a7cb951fSGabor Marton     Result += ", ";
814a7cb951fSGabor Marton     Max.toString(Result);
815a7cb951fSGabor Marton     Result += "]";
816a7cb951fSGabor Marton     if (--I > 0)
817a7cb951fSGabor Marton       Result += ", ";
818a7cb951fSGabor Marton   }
819a7cb951fSGabor Marton   if (Ranges.size() > 1)
820a7cb951fSGabor Marton     Result += "]";
821a7cb951fSGabor Marton 
822a7cb951fSGabor Marton   return Result.c_str();
823a7cb951fSGabor Marton }
824a7cb951fSGabor Marton 
825a7cb951fSGabor Marton SmallString<8>
getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN)826a7cb951fSGabor Marton StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) {
827a7cb951fSGabor Marton   SmallString<8> Result;
828a7cb951fSGabor Marton   Result += std::to_string(ArgN + 1);
829a7cb951fSGabor Marton   Result += llvm::getOrdinalSuffix(ArgN + 1);
830a7cb951fSGabor Marton   Result += " arg";
831a7cb951fSGabor Marton   return Result;
832a7cb951fSGabor Marton }
833a7cb951fSGabor Marton 
describe(ProgramStateRef State,const Summary & Summary) const834a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
835a7cb951fSGabor Marton     ProgramStateRef State, const Summary &Summary) const {
836a7cb951fSGabor Marton   SmallString<96> Result;
837a7cb951fSGabor Marton   Result += "The size of the ";
838a7cb951fSGabor Marton   Result += getArgDesc(ArgN);
839a7cb951fSGabor Marton   Result += " should be equal to or less than the value of ";
840a7cb951fSGabor Marton   if (ConcreteSize) {
841a7cb951fSGabor Marton     ConcreteSize->toString(Result);
842a7cb951fSGabor Marton   } else if (SizeArgN) {
843a7cb951fSGabor Marton     Result += "the ";
844a7cb951fSGabor Marton     Result += getArgDesc(*SizeArgN);
845a7cb951fSGabor Marton     if (SizeMultiplierArgN) {
846a7cb951fSGabor Marton       Result += " times the ";
847a7cb951fSGabor Marton       Result += getArgDesc(*SizeMultiplierArgN);
848a7cb951fSGabor Marton     }
849a7cb951fSGabor Marton   }
850a7cb951fSGabor Marton   return Result.c_str();
851a7cb951fSGabor Marton }
852a7cb951fSGabor Marton 
applyAsOutOfRange(ProgramStateRef State,const CallEvent & Call,const Summary & Summary) const853c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange(
854bba497fbSArtem Dergachev     ProgramStateRef State, const CallEvent &Call,
855f5086b38SGabor Marton     const Summary &Summary) const {
856a787a4edSGabor Marton   if (Ranges.empty())
857a787a4edSGabor Marton     return State;
858bba497fbSArtem Dergachev 
859bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
860bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
861bba497fbSArtem Dergachev   BasicValueFactory &BVF = SVB.getBasicValueFactory();
862bba497fbSArtem Dergachev   ConstraintManager &CM = Mgr.getConstraintManager();
86316506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
864bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
865bba497fbSArtem Dergachev 
866bba497fbSArtem Dergachev   if (auto N = V.getAs<NonLoc>()) {
867f5086b38SGabor Marton     const IntRangeVector &R = getRanges();
868bba497fbSArtem Dergachev     size_t E = R.size();
869bba497fbSArtem Dergachev     for (size_t I = 0; I != E; ++I) {
870bba497fbSArtem Dergachev       const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
871bba497fbSArtem Dergachev       const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
872bba497fbSArtem Dergachev       assert(Min <= Max);
8733f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
874bba497fbSArtem Dergachev       if (!State)
875bba497fbSArtem Dergachev         break;
876bba497fbSArtem Dergachev     }
877bba497fbSArtem Dergachev   }
878bba497fbSArtem Dergachev 
879bba497fbSArtem Dergachev   return State;
880bba497fbSArtem Dergachev }
881bba497fbSArtem Dergachev 
applyAsWithinRange(ProgramStateRef State,const CallEvent & Call,const Summary & Summary) const882c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange(
883bba497fbSArtem Dergachev     ProgramStateRef State, const CallEvent &Call,
884f5086b38SGabor Marton     const Summary &Summary) const {
885a787a4edSGabor Marton   if (Ranges.empty())
886a787a4edSGabor Marton     return State;
887bba497fbSArtem Dergachev 
888bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
889bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
890bba497fbSArtem Dergachev   BasicValueFactory &BVF = SVB.getBasicValueFactory();
891bba497fbSArtem Dergachev   ConstraintManager &CM = Mgr.getConstraintManager();
89216506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
893bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
894bba497fbSArtem Dergachev 
895bba497fbSArtem Dergachev   // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
896bba497fbSArtem Dergachev   // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
897bba497fbSArtem Dergachev   // and then cut away all holes in R one by one.
898536456a7SGabor Marton   //
899536456a7SGabor Marton   // E.g. consider a range list R as [A, B] and [C, D]
900536456a7SGabor Marton   // -------+--------+------------------+------------+----------->
901536456a7SGabor Marton   //        A        B                  C            D
902536456a7SGabor Marton   // Then we assume that the value is not in [-inf, A - 1],
903536456a7SGabor Marton   // then not in [D + 1, +inf], then not in [B + 1, C - 1]
904bba497fbSArtem Dergachev   if (auto N = V.getAs<NonLoc>()) {
905f5086b38SGabor Marton     const IntRangeVector &R = getRanges();
906bba497fbSArtem Dergachev     size_t E = R.size();
907bba497fbSArtem Dergachev 
908bba497fbSArtem Dergachev     const llvm::APSInt &MinusInf = BVF.getMinValue(T);
909bba497fbSArtem Dergachev     const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
910bba497fbSArtem Dergachev 
91126b0a9d8SArtem Dergachev     const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
912bba497fbSArtem Dergachev     if (Left != PlusInf) {
913bba497fbSArtem Dergachev       assert(MinusInf <= Left);
9143f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
915bba497fbSArtem Dergachev       if (!State)
916bba497fbSArtem Dergachev         return nullptr;
917bba497fbSArtem Dergachev     }
918bba497fbSArtem Dergachev 
91926b0a9d8SArtem Dergachev     const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
920bba497fbSArtem Dergachev     if (Right != MinusInf) {
921bba497fbSArtem Dergachev       assert(Right <= PlusInf);
9223f8c3fa7SDominic Chen       State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
923bba497fbSArtem Dergachev       if (!State)
924bba497fbSArtem Dergachev         return nullptr;
925bba497fbSArtem Dergachev     }
926bba497fbSArtem Dergachev 
927bba497fbSArtem Dergachev     for (size_t I = 1; I != E; ++I) {
92826b0a9d8SArtem Dergachev       const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
92926b0a9d8SArtem Dergachev       const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
930536456a7SGabor Marton       if (Min <= Max) {
9313f8c3fa7SDominic Chen         State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
932bba497fbSArtem Dergachev         if (!State)
933bba497fbSArtem Dergachev           return nullptr;
934bba497fbSArtem Dergachev       }
935bba497fbSArtem Dergachev     }
936536456a7SGabor Marton   }
937bba497fbSArtem Dergachev 
938bba497fbSArtem Dergachev   return State;
939bba497fbSArtem Dergachev }
940bba497fbSArtem Dergachev 
apply(ProgramStateRef State,const CallEvent & Call,const Summary & Summary,CheckerContext & C) const941c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply(
942bd03ef19SGabor Marton     ProgramStateRef State, const CallEvent &Call, const Summary &Summary,
943bd03ef19SGabor Marton     CheckerContext &C) const {
944bba497fbSArtem Dergachev 
945bba497fbSArtem Dergachev   ProgramStateManager &Mgr = State->getStateManager();
946bba497fbSArtem Dergachev   SValBuilder &SVB = Mgr.getSValBuilder();
947bba497fbSArtem Dergachev   QualType CondT = SVB.getConditionType();
94816506d78SGabor Marton   QualType T = Summary.getArgType(getArgNo());
949bba497fbSArtem Dergachev   SVal V = getArgSVal(Call, getArgNo());
950bba497fbSArtem Dergachev 
951bba497fbSArtem Dergachev   BinaryOperator::Opcode Op = getOpcode();
952f5086b38SGabor Marton   ArgNo OtherArg = getOtherArgNo();
953bba497fbSArtem Dergachev   SVal OtherV = getArgSVal(Call, OtherArg);
95416506d78SGabor Marton   QualType OtherT = Summary.getArgType(OtherArg);
955bba497fbSArtem Dergachev   // Note: we avoid integral promotion for comparison.
956bba497fbSArtem Dergachev   OtherV = SVB.evalCast(OtherV, T, OtherT);
957bba497fbSArtem Dergachev   if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
958bba497fbSArtem Dergachev                        .getAs<DefinedOrUnknownSVal>())
959bba497fbSArtem Dergachev     State = State->assume(*CompV, true);
960bba497fbSArtem Dergachev   return State;
961bba497fbSArtem Dergachev }
962bba497fbSArtem Dergachev 
checkPreCall(const CallEvent & Call,CheckerContext & C) const96394061df6SGabor Marton void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
96494061df6SGabor Marton                                               CheckerContext &C) const {
96594061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
96694061df6SGabor Marton   if (!FoundSummary)
96794061df6SGabor Marton     return;
96894061df6SGabor Marton 
96994061df6SGabor Marton   const Summary &Summary = *FoundSummary;
97094061df6SGabor Marton   ProgramStateRef State = C.getState();
97194061df6SGabor Marton 
9721525232eSGabor Marton   ProgramStateRef NewState = State;
97316506d78SGabor Marton   for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) {
97416506d78SGabor Marton     ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C);
97516506d78SGabor Marton     ProgramStateRef FailureSt =
97616506d78SGabor Marton         Constraint->negate()->apply(NewState, Call, Summary, C);
97794061df6SGabor Marton     // The argument constraint is not satisfied.
97894061df6SGabor Marton     if (FailureSt && !SuccessSt) {
9791525232eSGabor Marton       if (ExplodedNode *N = C.generateErrorNode(NewState))
980a7cb951fSGabor Marton         reportBug(Call, N, Constraint.get(), Summary, C);
98194061df6SGabor Marton       break;
98294061df6SGabor Marton     } else {
9831525232eSGabor Marton       // We will apply the constraint even if we cannot reason about the
9841525232eSGabor Marton       // argument. This means both SuccessSt and FailureSt can be true. If we
9851525232eSGabor Marton       // weren't applying the constraint that would mean that symbolic
9861525232eSGabor Marton       // execution continues on a code whose behaviour is undefined.
98794061df6SGabor Marton       assert(SuccessSt);
9881525232eSGabor Marton       NewState = SuccessSt;
98994061df6SGabor Marton     }
99094061df6SGabor Marton   }
9911525232eSGabor Marton   if (NewState && NewState != State)
9921525232eSGabor Marton     C.addTransition(NewState);
99394061df6SGabor Marton }
99494061df6SGabor Marton 
checkPostCall(const CallEvent & Call,CheckerContext & C) const995bba497fbSArtem Dergachev void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
996bba497fbSArtem Dergachev                                                CheckerContext &C) const {
99794061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
998bba497fbSArtem Dergachev   if (!FoundSummary)
999bba497fbSArtem Dergachev     return;
1000bba497fbSArtem Dergachev 
1001c6b8484eSGabor Marton   // Now apply the constraints.
1002f5086b38SGabor Marton   const Summary &Summary = *FoundSummary;
1003bba497fbSArtem Dergachev   ProgramStateRef State = C.getState();
1004f68c0a2fSArtem Dergachev   const ExplodedNode *Node = C.getPredecessor();
1005bba497fbSArtem Dergachev 
1006f5086b38SGabor Marton   // Apply case/branch specifications.
1007f68c0a2fSArtem Dergachev   for (const SummaryCase &Case : Summary.getCases()) {
1008bba497fbSArtem Dergachev     ProgramStateRef NewState = State;
1009f68c0a2fSArtem Dergachev     for (const ValueConstraintPtr &Constraint : Case.getConstraints()) {
101016506d78SGabor Marton       NewState = Constraint->apply(NewState, Call, Summary, C);
1011bba497fbSArtem Dergachev       if (!NewState)
1012bba497fbSArtem Dergachev         break;
1013bba497fbSArtem Dergachev     }
1014bba497fbSArtem Dergachev 
1015957014daSBalázs Kéri     if (NewState)
1016957014daSBalázs Kéri       NewState = Case.getErrnoConstraint().apply(NewState, Call, Summary, C);
1017957014daSBalázs Kéri 
1018f68c0a2fSArtem Dergachev     if (NewState && NewState != State) {
1019957014daSBalázs Kéri       if (Case.getNote().empty()) {
1020957014daSBalázs Kéri         std::string Note;
1021957014daSBalázs Kéri         if (const auto *D = dyn_cast_or_null<FunctionDecl>(Call.getDecl()))
1022957014daSBalázs Kéri           Note = Case.getErrnoConstraint().describe(D->getNameAsString());
1023957014daSBalázs Kéri         if (Note.empty())
1024957014daSBalázs Kéri           C.addTransition(NewState);
1025957014daSBalázs Kéri         else
1026957014daSBalázs Kéri           C.addTransition(NewState, errno_modeling::getErrnoNoteTag(C, Note));
1027957014daSBalázs Kéri       } else {
1028f68c0a2fSArtem Dergachev         StringRef Note = Case.getNote();
1029f68c0a2fSArtem Dergachev         const NoteTag *Tag = C.getNoteTag(
1030f68c0a2fSArtem Dergachev             // Sorry couldn't help myself.
1031957014daSBalázs Kéri             [Node, Note]() -> std::string {
1032f68c0a2fSArtem Dergachev               // Don't emit "Assuming..." note when we ended up
1033f68c0a2fSArtem Dergachev               // knowing in advance which branch is taken.
1034f68c0a2fSArtem Dergachev               return (Node->succ_size() > 1) ? Note.str() : "";
1035f68c0a2fSArtem Dergachev             },
1036f68c0a2fSArtem Dergachev             /*IsPrunable=*/true);
1037f68c0a2fSArtem Dergachev         C.addTransition(NewState, Tag);
1038f68c0a2fSArtem Dergachev       }
1039bba497fbSArtem Dergachev     }
1040bba497fbSArtem Dergachev   }
1041957014daSBalázs Kéri }
1042bba497fbSArtem Dergachev 
evalCall(const CallEvent & Call,CheckerContext & C) const104344820630SArtem Dergachev bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
1044bba497fbSArtem Dergachev                                           CheckerContext &C) const {
104594061df6SGabor Marton   Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
1046bba497fbSArtem Dergachev   if (!FoundSummary)
1047bba497fbSArtem Dergachev     return false;
1048bba497fbSArtem Dergachev 
1049f5086b38SGabor Marton   const Summary &Summary = *FoundSummary;
105016506d78SGabor Marton   switch (Summary.getInvalidationKd()) {
1051bba497fbSArtem Dergachev   case EvalCallAsPure: {
1052bba497fbSArtem Dergachev     ProgramStateRef State = C.getState();
1053bba497fbSArtem Dergachev     const LocationContext *LC = C.getLocationContext();
1054879c12d9SSimon Pilgrim     const auto *CE = cast<CallExpr>(Call.getOriginExpr());
1055bba497fbSArtem Dergachev     SVal V = C.getSValBuilder().conjureSymbolVal(
1056bba497fbSArtem Dergachev         CE, LC, CE->getType().getCanonicalType(), C.blockCount());
1057bba497fbSArtem Dergachev     State = State->BindExpr(CE, LC, V);
1058957014daSBalázs Kéri 
1059bba497fbSArtem Dergachev     C.addTransition(State);
1060957014daSBalázs Kéri 
1061bba497fbSArtem Dergachev     return true;
1062bba497fbSArtem Dergachev   }
1063bba497fbSArtem Dergachev   case NoEvalCall:
1064bba497fbSArtem Dergachev     // Summary tells us to avoid performing eval::Call. The function is possibly
1065bba497fbSArtem Dergachev     // evaluated by another checker, or evaluated conservatively.
1066bba497fbSArtem Dergachev     return false;
1067bba497fbSArtem Dergachev   }
1068bba497fbSArtem Dergachev   llvm_unreachable("Unknown invalidation kind!");
1069bba497fbSArtem Dergachev }
1070bba497fbSArtem Dergachev 
matches(const FunctionDecl * FD) const107116506d78SGabor Marton bool StdLibraryFunctionsChecker::Signature::matches(
10728f961399SGabor Marton     const FunctionDecl *FD) const {
1073a787a4edSGabor Marton   assert(!isInvalid());
1074fe0972d3SGabor Marton   // Check the number of arguments.
10758f961399SGabor Marton   if (FD->param_size() != ArgTys.size())
1076bba497fbSArtem Dergachev     return false;
1077bba497fbSArtem Dergachev 
1078fe0972d3SGabor Marton   // The "restrict" keyword is illegal in C++, however, many libc
1079fe0972d3SGabor Marton   // implementations use the "__restrict" compiler intrinsic in functions
1080fe0972d3SGabor Marton   // prototypes. The "__restrict" keyword qualifies a type as a restricted type
1081fe0972d3SGabor Marton   // even in C++.
1082fe0972d3SGabor Marton   // In case of any non-C99 languages, we don't want to match based on the
1083fe0972d3SGabor Marton   // restrict qualifier because we cannot know if the given libc implementation
1084fe0972d3SGabor Marton   // qualifies the paramter type or not.
1085fe0972d3SGabor Marton   auto RemoveRestrict = [&FD](QualType T) {
1086fe0972d3SGabor Marton     if (!FD->getASTContext().getLangOpts().C99)
1087fe0972d3SGabor Marton       T.removeLocalRestrict();
1088fe0972d3SGabor Marton     return T;
1089fe0972d3SGabor Marton   };
1090bba497fbSArtem Dergachev 
1091fe0972d3SGabor Marton   // Check the return type.
1092fe0972d3SGabor Marton   if (!isIrrelevant(RetTy)) {
1093fe0972d3SGabor Marton     QualType FDRetTy = RemoveRestrict(FD->getReturnType().getCanonicalType());
1094fe0972d3SGabor Marton     if (RetTy != FDRetTy)
1095fe0972d3SGabor Marton       return false;
1096fe0972d3SGabor Marton   }
1097fe0972d3SGabor Marton 
1098fe0972d3SGabor Marton   // Check the argument types.
1099f5086b38SGabor Marton   for (size_t I = 0, E = ArgTys.size(); I != E; ++I) {
110016506d78SGabor Marton     QualType ArgTy = ArgTys[I];
110116506d78SGabor Marton     if (isIrrelevant(ArgTy))
1102bba497fbSArtem Dergachev       continue;
1103fe0972d3SGabor Marton     QualType FDArgTy =
1104fe0972d3SGabor Marton         RemoveRestrict(FD->getParamDecl(I)->getType().getCanonicalType());
1105fe0972d3SGabor Marton     if (ArgTy != FDArgTy)
1106bba497fbSArtem Dergachev       return false;
1107bba497fbSArtem Dergachev   }
1108bba497fbSArtem Dergachev 
1109bba497fbSArtem Dergachev   return true;
1110bba497fbSArtem Dergachev }
1111bba497fbSArtem Dergachev 
1112f5086b38SGabor Marton Optional<StdLibraryFunctionsChecker::Summary>
findFunctionSummary(const FunctionDecl * FD,CheckerContext & C) const1113bba497fbSArtem Dergachev StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
1114bba497fbSArtem Dergachev                                                 CheckerContext &C) const {
1115bba497fbSArtem Dergachev   if (!FD)
1116bba497fbSArtem Dergachev     return None;
1117bba497fbSArtem Dergachev 
1118536456a7SGabor Marton   initFunctionSummaries(C);
1119bba497fbSArtem Dergachev 
112062e747f6SGabor Marton   auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl());
1121bba497fbSArtem Dergachev   if (FSMI == FunctionSummaryMap.end())
1122bba497fbSArtem Dergachev     return None;
112362e747f6SGabor Marton   return FSMI->second;
1124bba497fbSArtem Dergachev }
1125bba497fbSArtem Dergachev 
112694061df6SGabor Marton Optional<StdLibraryFunctionsChecker::Summary>
findFunctionSummary(const CallEvent & Call,CheckerContext & C) const112794061df6SGabor Marton StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call,
112894061df6SGabor Marton                                                 CheckerContext &C) const {
112994061df6SGabor Marton   const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
113094061df6SGabor Marton   if (!FD)
113194061df6SGabor Marton     return None;
11328f961399SGabor Marton   return findFunctionSummary(FD, C);
113394061df6SGabor Marton }
113494061df6SGabor Marton 
initFunctionSummaries(CheckerContext & C) const1135a787a4edSGabor Marton void StdLibraryFunctionsChecker::initFunctionSummaries(
1136a787a4edSGabor Marton     CheckerContext &C) const {
1137c7635040SValeriy Savchenko   if (SummariesInitialized)
1138a787a4edSGabor Marton     return;
1139a787a4edSGabor Marton 
1140a787a4edSGabor Marton   SValBuilder &SVB = C.getSValBuilder();
1141a787a4edSGabor Marton   BasicValueFactory &BVF = SVB.getBasicValueFactory();
1142a787a4edSGabor Marton   const ASTContext &ACtx = BVF.getContext();
1143a787a4edSGabor Marton 
1144a787a4edSGabor Marton   // Helper class to lookup a type by its name.
1145a787a4edSGabor Marton   class LookupType {
1146a787a4edSGabor Marton     const ASTContext &ACtx;
1147a787a4edSGabor Marton 
1148a787a4edSGabor Marton   public:
1149a787a4edSGabor Marton     LookupType(const ASTContext &ACtx) : ACtx(ACtx) {}
1150a787a4edSGabor Marton 
1151a787a4edSGabor Marton     // Find the type. If not found then the optional is not set.
1152a787a4edSGabor Marton     llvm::Optional<QualType> operator()(StringRef Name) {
1153634258b8SGabor Marton       IdentifierInfo &II = ACtx.Idents.get(Name);
1154634258b8SGabor Marton       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
11550cb7e7caSVassil Vassilev       if (LookupRes.empty())
1156634258b8SGabor Marton         return None;
1157634258b8SGabor Marton 
1158634258b8SGabor Marton       // Prioritze typedef declarations.
1159634258b8SGabor Marton       // This is needed in case of C struct typedefs. E.g.:
1160634258b8SGabor Marton       //   typedef struct FILE FILE;
1161a787a4edSGabor Marton       // In this case, we have a RecordDecl 'struct FILE' with the name 'FILE'
1162a787a4edSGabor Marton       // and we have a TypedefDecl with the name 'FILE'.
1163db4d5f70SGabor Marton       for (Decl *D : LookupRes)
1164634258b8SGabor Marton         if (auto *TD = dyn_cast<TypedefNameDecl>(D))
1165634258b8SGabor Marton           return ACtx.getTypeDeclType(TD).getCanonicalType();
1166db4d5f70SGabor Marton 
1167db4d5f70SGabor Marton       // Find the first TypeDecl.
1168db4d5f70SGabor Marton       // There maybe cases when a function has the same name as a struct.
1169db4d5f70SGabor Marton       // E.g. in POSIX: `struct stat` and the function `stat()`:
1170db4d5f70SGabor Marton       //   int stat(const char *restrict path, struct stat *restrict buf);
1171db4d5f70SGabor Marton       for (Decl *D : LookupRes)
1172db4d5f70SGabor Marton         if (auto *TD = dyn_cast<TypeDecl>(D))
1173db4d5f70SGabor Marton           return ACtx.getTypeDeclType(TD).getCanonicalType();
1174db4d5f70SGabor Marton       return None;
1175634258b8SGabor Marton     }
1176a787a4edSGabor Marton   } lookupTy(ACtx);
1177634258b8SGabor Marton 
1178a787a4edSGabor Marton   // Below are auxiliary classes to handle optional types that we get as a
1179a787a4edSGabor Marton   // result of the lookup.
1180a787a4edSGabor Marton   class GetRestrictTy {
1181a787a4edSGabor Marton     const ASTContext &ACtx;
1182bba497fbSArtem Dergachev 
1183a787a4edSGabor Marton   public:
1184a787a4edSGabor Marton     GetRestrictTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1185a787a4edSGabor Marton     QualType operator()(QualType Ty) {
11863ff220deSGabor Marton       return ACtx.getLangOpts().C99 ? ACtx.getRestrictType(Ty) : Ty;
1187a787a4edSGabor Marton     }
1188a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1189a787a4edSGabor Marton       if (Ty)
1190a787a4edSGabor Marton         return operator()(*Ty);
1191a787a4edSGabor Marton       return None;
1192a787a4edSGabor Marton     }
1193a787a4edSGabor Marton   } getRestrictTy(ACtx);
1194a787a4edSGabor Marton   class GetPointerTy {
1195a787a4edSGabor Marton     const ASTContext &ACtx;
1196a787a4edSGabor Marton 
1197a787a4edSGabor Marton   public:
1198a787a4edSGabor Marton     GetPointerTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1199a787a4edSGabor Marton     QualType operator()(QualType Ty) { return ACtx.getPointerType(Ty); }
1200a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1201a787a4edSGabor Marton       if (Ty)
1202a787a4edSGabor Marton         return operator()(*Ty);
1203a787a4edSGabor Marton       return None;
1204a787a4edSGabor Marton     }
1205a787a4edSGabor Marton   } getPointerTy(ACtx);
1206a787a4edSGabor Marton   class {
1207a787a4edSGabor Marton   public:
1208a787a4edSGabor Marton     Optional<QualType> operator()(Optional<QualType> Ty) {
1209a787a4edSGabor Marton       return Ty ? Optional<QualType>(Ty->withConst()) : None;
1210a787a4edSGabor Marton     }
1211a787a4edSGabor Marton     QualType operator()(QualType Ty) { return Ty.withConst(); }
1212a787a4edSGabor Marton   } getConstTy;
1213a787a4edSGabor Marton   class GetMaxValue {
1214a787a4edSGabor Marton     BasicValueFactory &BVF;
1215a787a4edSGabor Marton 
1216a787a4edSGabor Marton   public:
1217a787a4edSGabor Marton     GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {}
1218a787a4edSGabor Marton     Optional<RangeInt> operator()(QualType Ty) {
1219a787a4edSGabor Marton       return BVF.getMaxValue(Ty).getLimitedValue();
1220a787a4edSGabor Marton     }
1221a787a4edSGabor Marton     Optional<RangeInt> operator()(Optional<QualType> Ty) {
1222a787a4edSGabor Marton       if (Ty) {
1223a787a4edSGabor Marton         return operator()(*Ty);
1224a787a4edSGabor Marton       }
1225a787a4edSGabor Marton       return None;
1226a787a4edSGabor Marton     }
1227a787a4edSGabor Marton   } getMaxValue(BVF);
12283ff220deSGabor Marton 
1229bba497fbSArtem Dergachev   // These types are useful for writing specifications quickly,
1230bba497fbSArtem Dergachev   // New specifications should probably introduce more types.
123147fec16cSArtem Dergachev   // Some types are hard to obtain from the AST, eg. "ssize_t".
123247fec16cSArtem Dergachev   // In such cases it should be possible to provide multiple variants
123347fec16cSArtem Dergachev   // of function summary for common cases (eg. ssize_t could be int or long
123447fec16cSArtem Dergachev   // or long long, so three summary variants would be enough).
123547fec16cSArtem Dergachev   // Of course, function variants are also useful for C++ overloads.
1236db4d5f70SGabor Marton   const QualType VoidTy = ACtx.VoidTy;
1237a787a4edSGabor Marton   const QualType CharTy = ACtx.CharTy;
1238a787a4edSGabor Marton   const QualType WCharTy = ACtx.WCharTy;
1239536456a7SGabor Marton   const QualType IntTy = ACtx.IntTy;
1240db4d5f70SGabor Marton   const QualType UnsignedIntTy = ACtx.UnsignedIntTy;
1241536456a7SGabor Marton   const QualType LongTy = ACtx.LongTy;
1242536456a7SGabor Marton   const QualType SizeTy = ACtx.getSizeType();
1243db4d5f70SGabor Marton 
1244a787a4edSGabor Marton   const QualType VoidPtrTy = getPointerTy(VoidTy); // void *
1245a787a4edSGabor Marton   const QualType IntPtrTy = getPointerTy(IntTy);   // int *
1246db4d5f70SGabor Marton   const QualType UnsignedIntPtrTy =
1247a787a4edSGabor Marton       getPointerTy(UnsignedIntTy); // unsigned int *
12483ff220deSGabor Marton   const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy);
1249ededa65dSGabor Marton   const QualType ConstVoidPtrTy =
1250a787a4edSGabor Marton       getPointerTy(getConstTy(VoidTy));            // const void *
1251a787a4edSGabor Marton   const QualType CharPtrTy = getPointerTy(CharTy); // char *
12523ff220deSGabor Marton   const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy);
12538f961399SGabor Marton   const QualType ConstCharPtrTy =
1254a787a4edSGabor Marton       getPointerTy(getConstTy(CharTy)); // const char *
12553ff220deSGabor Marton   const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy);
1256a787a4edSGabor Marton   const QualType Wchar_tPtrTy = getPointerTy(WCharTy); // wchar_t *
1257db4d5f70SGabor Marton   const QualType ConstWchar_tPtrTy =
1258a787a4edSGabor Marton       getPointerTy(getConstTy(WCharTy)); // const wchar_t *
12593ff220deSGabor Marton   const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy);
1260d0128058SGabor Marton   const QualType SizePtrTy = getPointerTy(SizeTy);
1261d0128058SGabor Marton   const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy);
1262bba497fbSArtem Dergachev 
1263536456a7SGabor Marton   const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
1264db4d5f70SGabor Marton   const RangeInt UnsignedIntMax =
1265db4d5f70SGabor Marton       BVF.getMaxValue(UnsignedIntTy).getLimitedValue();
1266536456a7SGabor Marton   const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
1267db4d5f70SGabor Marton   const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue();
1268536456a7SGabor Marton 
12690eba5dc8SArtem Dergachev   // Set UCharRangeMax to min of int or uchar maximum value.
12700eba5dc8SArtem Dergachev   // The C standard states that the arguments of functions like isalpha must
12710eba5dc8SArtem Dergachev   // be representable as an unsigned char. Their type is 'int', so the max
12720eba5dc8SArtem Dergachev   // value of the argument should be min(UCharMax, IntMax). This just happen
12730eba5dc8SArtem Dergachev   // to be true for commonly used and well tested instruction set
12740eba5dc8SArtem Dergachev   // architectures, but not for others.
12750eba5dc8SArtem Dergachev   const RangeInt UCharRangeMax =
12760eba5dc8SArtem Dergachev       std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax);
1277536456a7SGabor Marton 
1278536456a7SGabor Marton   // The platform dependent value of EOF.
1279536456a7SGabor Marton   // Try our best to parse this from the Preprocessor, otherwise fallback to -1.
1280536456a7SGabor Marton   const auto EOFv = [&C]() -> RangeInt {
1281536456a7SGabor Marton     if (const llvm::Optional<int> OptInt =
1282536456a7SGabor Marton             tryExpandAsInteger("EOF", C.getPreprocessor()))
1283536456a7SGabor Marton       return *OptInt;
1284536456a7SGabor Marton     return -1;
1285536456a7SGabor Marton   }();
1286bba497fbSArtem Dergachev 
128762e747f6SGabor Marton   // Auxiliary class to aid adding summaries to the summary map.
128862e747f6SGabor Marton   struct AddToFunctionSummaryMap {
128962e747f6SGabor Marton     const ASTContext &ACtx;
129062e747f6SGabor Marton     FunctionSummaryMapType &Map;
1291ff4492c8SGabor Marton     bool DisplayLoadedSummaries;
1292ff4492c8SGabor Marton     AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM,
1293ff4492c8SGabor Marton                             bool DisplayLoadedSummaries)
1294ff4492c8SGabor Marton         : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) {
1295ff4492c8SGabor Marton     }
1296ff4492c8SGabor Marton 
129762e747f6SGabor Marton     // Add a summary to a FunctionDecl found by lookup. The lookup is performed
129862e747f6SGabor Marton     // by the given Name, and in the global scope. The summary will be attached
129962e747f6SGabor Marton     // to the found FunctionDecl only if the signatures match.
13003ff220deSGabor Marton     //
13013ff220deSGabor Marton     // Returns true if the summary has been added, false otherwise.
130211d2e63aSGabor Marton     bool operator()(StringRef Name, Signature Sign, Summary Sum) {
130311d2e63aSGabor Marton       if (Sign.isInvalid())
1304a787a4edSGabor Marton         return false;
130562e747f6SGabor Marton       IdentifierInfo &II = ACtx.Idents.get(Name);
130662e747f6SGabor Marton       auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
13070cb7e7caSVassil Vassilev       if (LookupRes.empty())
13083ff220deSGabor Marton         return false;
130962e747f6SGabor Marton       for (Decl *D : LookupRes) {
131062e747f6SGabor Marton         if (auto *FD = dyn_cast<FunctionDecl>(D)) {
131111d2e63aSGabor Marton           if (Sum.matchesAndSet(Sign, FD)) {
131211d2e63aSGabor Marton             auto Res = Map.insert({FD->getCanonicalDecl(), Sum});
131362e747f6SGabor Marton             assert(Res.second && "Function already has a summary set!");
131462e747f6SGabor Marton             (void)Res;
1315ff4492c8SGabor Marton             if (DisplayLoadedSummaries) {
1316ff4492c8SGabor Marton               llvm::errs() << "Loaded summary for: ";
1317ff4492c8SGabor Marton               FD->print(llvm::errs());
1318ff4492c8SGabor Marton               llvm::errs() << "\n";
1319ff4492c8SGabor Marton             }
13203ff220deSGabor Marton             return true;
132162e747f6SGabor Marton           }
132262e747f6SGabor Marton         }
132362e747f6SGabor Marton       }
13243ff220deSGabor Marton       return false;
13253ff220deSGabor Marton     }
1326fe0972d3SGabor Marton     // Add the same summary for different names with the Signature explicitly
1327fe0972d3SGabor Marton     // given.
1328fe0972d3SGabor Marton     void operator()(std::vector<StringRef> Names, Signature Sign, Summary Sum) {
1329fe0972d3SGabor Marton       for (StringRef Name : Names)
1330fe0972d3SGabor Marton         operator()(Name, Sign, Sum);
1331fe0972d3SGabor Marton     }
1332ff4492c8SGabor Marton   } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries);
133362e747f6SGabor Marton 
1334c6b8484eSGabor Marton   // Below are helpers functions to create the summaries.
1335c6b8484eSGabor Marton   auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind,
1336c6b8484eSGabor Marton                               IntRangeVector Ranges) {
1337c6b8484eSGabor Marton     return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges);
1338f5086b38SGabor Marton   };
133941928c97SGabor Marton   auto BufferSize = [](auto... Args) {
134041928c97SGabor Marton     return std::make_shared<BufferSizeConstraint>(Args...);
1341bd03ef19SGabor Marton   };
1342c6b8484eSGabor Marton   struct {
1343c6b8484eSGabor Marton     auto operator()(RangeKind Kind, IntRangeVector Ranges) {
1344c6b8484eSGabor Marton       return std::make_shared<RangeConstraint>(Ret, Kind, Ranges);
1345c6b8484eSGabor Marton     }
1346c6b8484eSGabor Marton     auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) {
1347c6b8484eSGabor Marton       return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN);
1348c6b8484eSGabor Marton     }
1349c6b8484eSGabor Marton   } ReturnValueCondition;
1350a787a4edSGabor Marton   struct {
1351a787a4edSGabor Marton     auto operator()(RangeInt b, RangeInt e) {
1352f5086b38SGabor Marton       return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}};
1353a787a4edSGabor Marton     }
1354a787a4edSGabor Marton     auto operator()(RangeInt b, Optional<RangeInt> e) {
1355a787a4edSGabor Marton       if (e)
1356a787a4edSGabor Marton         return IntRangeVector{std::pair<RangeInt, RangeInt>{b, *e}};
1357a787a4edSGabor Marton       return IntRangeVector{};
1358a787a4edSGabor Marton     }
1359d63a945aSGabor Marton     auto operator()(std::pair<RangeInt, RangeInt> i0,
1360d63a945aSGabor Marton                     std::pair<RangeInt, Optional<RangeInt>> i1) {
1361d63a945aSGabor Marton       if (i1.second)
1362d63a945aSGabor Marton         return IntRangeVector{i0, {i1.first, *(i1.second)}};
1363d63a945aSGabor Marton       return IntRangeVector{i0};
1364d63a945aSGabor Marton     }
1365a787a4edSGabor Marton   } Range;
1366f5086b38SGabor Marton   auto SingleValue = [](RangeInt v) {
1367f5086b38SGabor Marton     return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}};
1368f5086b38SGabor Marton   };
1369c6b8484eSGabor Marton   auto LessThanOrEq = BO_LE;
1370ededa65dSGabor Marton   auto NotNull = [&](ArgNo ArgN) {
1371ededa65dSGabor Marton     return std::make_shared<NotNullConstraint>(ArgN);
1372ededa65dSGabor Marton   };
1373f5086b38SGabor Marton 
1374a787a4edSGabor Marton   Optional<QualType> FileTy = lookupTy("FILE");
1375a787a4edSGabor Marton   Optional<QualType> FilePtrTy = getPointerTy(FileTy);
1376a787a4edSGabor Marton   Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy);
1377634258b8SGabor Marton 
1378a787a4edSGabor Marton   // We are finally ready to define specifications for all supported functions.
1379a787a4edSGabor Marton   //
1380a787a4edSGabor Marton   // Argument ranges should always cover all variants. If return value
1381a787a4edSGabor Marton   // is completely unknown, omit it from the respective range set.
1382a787a4edSGabor Marton   //
1383a787a4edSGabor Marton   // Every item in the list of range sets represents a particular
1384a787a4edSGabor Marton   // execution path the analyzer would need to explore once
1385a787a4edSGabor Marton   // the call is modeled - a new program state is constructed
1386a787a4edSGabor Marton   // for every range set, and each range line in the range set
1387a787a4edSGabor Marton   // corresponds to a specific constraint within this state.
1388a787a4edSGabor Marton 
1389bba497fbSArtem Dergachev   // The isascii() family of functions.
139094061df6SGabor Marton   // The behavior is undefined if the value of the argument is not
139194061df6SGabor Marton   // representable as unsigned char or is not equal to EOF. See e.g. C99
139294061df6SGabor Marton   // 7.4.1.2 The isalpha function (p: 181-182).
139362e747f6SGabor Marton   addToFunctionSummaryMap(
139411d2e63aSGabor Marton       "isalnum", Signature(ArgTypes{IntTy}, RetType{IntTy}),
139511d2e63aSGabor Marton       Summary(EvalCallAsPure)
1396f5086b38SGabor Marton           // Boils down to isupper() or islower() or isdigit().
139762e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange,
1398f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}),
1399f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1400957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is alphanumeric")
1401f5086b38SGabor Marton           // The locale-specific range.
1402bba497fbSArtem Dergachev           // No post-condition. We are completely unaware of
1403bba497fbSArtem Dergachev           // locale-specific return values.
1404957014daSBalázs Kéri           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1405957014daSBalázs Kéri                 ErrnoIrrelevant)
140662e747f6SGabor Marton           .Case(
140762e747f6SGabor Marton               {ArgumentCondition(
140862e747f6SGabor Marton                    0U, OutOfRange,
140962e747f6SGabor Marton                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1410f68c0a2fSArtem Dergachev                ReturnValueCondition(WithinRange, SingleValue(0))},
1411957014daSBalázs Kéri               ErrnoIrrelevant, "Assuming the character is non-alphanumeric")
141294061df6SGabor Marton           .ArgConstraint(ArgumentCondition(
141362e747f6SGabor Marton               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
141462e747f6SGabor Marton   addToFunctionSummaryMap(
141511d2e63aSGabor Marton       "isalpha", Signature(ArgTypes{IntTy}, RetType{IntTy}),
141611d2e63aSGabor Marton       Summary(EvalCallAsPure)
141762e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}),
1418f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1419957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is alphabetical")
1420f5086b38SGabor Marton           // The locale-specific range.
1421957014daSBalázs Kéri           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1422957014daSBalázs Kéri                 ErrnoIrrelevant)
1423536456a7SGabor Marton           .Case({ArgumentCondition(
1424536456a7SGabor Marton                      0U, OutOfRange,
14250eba5dc8SArtem Dergachev                      {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1426f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1427957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is non-alphabetical"));
142862e747f6SGabor Marton   addToFunctionSummaryMap(
142911d2e63aSGabor Marton       "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
143011d2e63aSGabor Marton       Summary(EvalCallAsPure)
1431f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1432f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1433957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is an ASCII character")
1434f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)),
1435f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1436957014daSBalázs Kéri                 ErrnoIrrelevant,
1437f68c0a2fSArtem Dergachev                 "Assuming the character is not an ASCII character"));
143862e747f6SGabor Marton   addToFunctionSummaryMap(
143911d2e63aSGabor Marton       "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}),
144011d2e63aSGabor Marton       Summary(EvalCallAsPure)
144162e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}),
1442f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1443957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is a blank character")
144462e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}),
1445f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1446957014daSBalázs Kéri                 ErrnoIrrelevant,
1447f68c0a2fSArtem Dergachev                 "Assuming the character is not a blank character"));
144862e747f6SGabor Marton   addToFunctionSummaryMap(
144911d2e63aSGabor Marton       "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}),
145011d2e63aSGabor Marton       Summary(EvalCallAsPure)
145162e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}),
1452f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1453957014daSBalázs Kéri                 ErrnoIrrelevant,
1454f68c0a2fSArtem Dergachev                 "Assuming the character is a control character")
145562e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}),
1456f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1457957014daSBalázs Kéri                 ErrnoIrrelevant,
1458f68c0a2fSArtem Dergachev                 "Assuming the character is not a control character"));
145962e747f6SGabor Marton   addToFunctionSummaryMap(
146011d2e63aSGabor Marton       "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
146111d2e63aSGabor Marton       Summary(EvalCallAsPure)
1462f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')),
1463f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1464957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is a digit")
1465f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')),
1466f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1467957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is not a digit"));
146862e747f6SGabor Marton   addToFunctionSummaryMap(
146911d2e63aSGabor Marton       "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}),
147011d2e63aSGabor Marton       Summary(EvalCallAsPure)
1471f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)),
1472f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1473957014daSBalázs Kéri                 ErrnoIrrelevant,
1474f68c0a2fSArtem Dergachev                 "Assuming the character has graphical representation")
1475f68c0a2fSArtem Dergachev           .Case(
1476f68c0a2fSArtem Dergachev               {ArgumentCondition(0U, OutOfRange, Range(33, 126)),
1477f68c0a2fSArtem Dergachev                ReturnValueCondition(WithinRange, SingleValue(0))},
1478957014daSBalázs Kéri               ErrnoIrrelevant,
1479f68c0a2fSArtem Dergachev               "Assuming the character does not have graphical representation"));
148062e747f6SGabor Marton   addToFunctionSummaryMap(
148111d2e63aSGabor Marton       "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
148211d2e63aSGabor Marton       Summary(EvalCallAsPure)
1483f5086b38SGabor Marton           // Is certainly lowercase.
1484f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')),
1485f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1486957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is a lowercase letter")
1487f5086b38SGabor Marton           // Is ascii but not lowercase.
1488f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1489f5086b38SGabor Marton                  ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
1490f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1491957014daSBalázs Kéri                 ErrnoIrrelevant,
1492f68c0a2fSArtem Dergachev                 "Assuming the character is not a lowercase letter")
1493f5086b38SGabor Marton           // The locale-specific range.
1494957014daSBalázs Kéri           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1495957014daSBalázs Kéri                 ErrnoIrrelevant)
1496f5086b38SGabor Marton           // Is not an unsigned char.
149762e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)),
1498957014daSBalázs Kéri                  ReturnValueCondition(WithinRange, SingleValue(0))},
1499957014daSBalázs Kéri                 ErrnoIrrelevant));
150062e747f6SGabor Marton   addToFunctionSummaryMap(
150111d2e63aSGabor Marton       "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
150211d2e63aSGabor Marton       Summary(EvalCallAsPure)
1503f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
1504f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1505957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is printable")
1506f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
1507f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1508957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is non-printable"));
150962e747f6SGabor Marton   addToFunctionSummaryMap(
151011d2e63aSGabor Marton       "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}),
151111d2e63aSGabor Marton       Summary(EvalCallAsPure)
1512f5086b38SGabor Marton           .Case({ArgumentCondition(
1513f5086b38SGabor Marton                      0U, WithinRange,
1514f5086b38SGabor Marton                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1515f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1516957014daSBalázs Kéri                 ErrnoIrrelevant, "Assuming the character is a punctuation mark")
1517f5086b38SGabor Marton           .Case({ArgumentCondition(
1518f5086b38SGabor Marton                      0U, OutOfRange,
1519f5086b38SGabor Marton                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1520f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1521957014daSBalázs Kéri                 ErrnoIrrelevant,
1522f68c0a2fSArtem Dergachev                 "Assuming the character is not a punctuation mark"));
152362e747f6SGabor Marton   addToFunctionSummaryMap(
152411d2e63aSGabor Marton       "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}),
152511d2e63aSGabor Marton       Summary(EvalCallAsPure)
1526f5086b38SGabor Marton           // Space, '\f', '\n', '\r', '\t', '\v'.
152762e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}),
1528f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1529957014daSBalázs Kéri                 ErrnoIrrelevant,
1530f68c0a2fSArtem Dergachev                 "Assuming the character is a whitespace character")
1531f5086b38SGabor Marton           // The locale-specific range.
1532957014daSBalázs Kéri           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1533957014daSBalázs Kéri                 ErrnoIrrelevant)
153462e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
15350eba5dc8SArtem Dergachev                                    {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
1536f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1537957014daSBalázs Kéri                 ErrnoIrrelevant,
1538f68c0a2fSArtem Dergachev                 "Assuming the character is not a whitespace character"));
153962e747f6SGabor Marton   addToFunctionSummaryMap(
154011d2e63aSGabor Marton       "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
154111d2e63aSGabor Marton       Summary(EvalCallAsPure)
1542f5086b38SGabor Marton           // Is certainly uppercase.
1543f5086b38SGabor Marton           .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
1544f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1545957014daSBalázs Kéri                 ErrnoIrrelevant,
1546f68c0a2fSArtem Dergachev                 "Assuming the character is an uppercase letter")
1547f5086b38SGabor Marton           // The locale-specific range.
1548957014daSBalázs Kéri           .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
1549957014daSBalázs Kéri                 ErrnoIrrelevant)
1550f5086b38SGabor Marton           // Other.
1551f5086b38SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
15520eba5dc8SArtem Dergachev                                    {{'A', 'Z'}, {128, UCharRangeMax}}),
1553f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1554957014daSBalázs Kéri                 ErrnoIrrelevant,
1555f68c0a2fSArtem Dergachev                 "Assuming the character is not an uppercase letter"));
155662e747f6SGabor Marton   addToFunctionSummaryMap(
155711d2e63aSGabor Marton       "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
155811d2e63aSGabor Marton       Summary(EvalCallAsPure)
155962e747f6SGabor Marton           .Case({ArgumentCondition(0U, WithinRange,
1560f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1561f68c0a2fSArtem Dergachev                  ReturnValueCondition(OutOfRange, SingleValue(0))},
1562957014daSBalázs Kéri                 ErrnoIrrelevant,
1563f68c0a2fSArtem Dergachev                 "Assuming the character is a hexadecimal digit")
156462e747f6SGabor Marton           .Case({ArgumentCondition(0U, OutOfRange,
1565f5086b38SGabor Marton                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1566f68c0a2fSArtem Dergachev                  ReturnValueCondition(WithinRange, SingleValue(0))},
1567957014daSBalázs Kéri                 ErrnoIrrelevant,
1568f68c0a2fSArtem Dergachev                 "Assuming the character is not a hexadecimal digit"));
156925bbe234SZurab Tsinadze   addToFunctionSummaryMap(
157011d2e63aSGabor Marton       "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
157111d2e63aSGabor Marton       Summary(EvalCallAsPure)
157225bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
157325bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
157425bbe234SZurab Tsinadze   addToFunctionSummaryMap(
157511d2e63aSGabor Marton       "tolower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
157611d2e63aSGabor Marton       Summary(EvalCallAsPure)
157725bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
157825bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
157925bbe234SZurab Tsinadze   addToFunctionSummaryMap(
158011d2e63aSGabor Marton       "toascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
158111d2e63aSGabor Marton       Summary(EvalCallAsPure)
158225bbe234SZurab Tsinadze           .ArgConstraint(ArgumentCondition(
158325bbe234SZurab Tsinadze               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1584bba497fbSArtem Dergachev 
1585bba497fbSArtem Dergachev   // The getc() family of functions that returns either a char or an EOF.
1586a012bc4cSGabor Marton   addToFunctionSummaryMap(
1587a012bc4cSGabor Marton       {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1588a012bc4cSGabor Marton       Summary(NoEvalCall)
1589a012bc4cSGabor Marton           .Case({ReturnValueCondition(WithinRange,
1590957014daSBalázs Kéri                                       {{EOFv, EOFv}, {0, UCharRangeMax}})},
1591957014daSBalázs Kéri                 ErrnoIrrelevant));
159262e747f6SGabor Marton   addToFunctionSummaryMap(
159311d2e63aSGabor Marton       "getchar", Signature(ArgTypes{}, RetType{IntTy}),
159411d2e63aSGabor Marton       Summary(NoEvalCall)
159511d2e63aSGabor Marton           .Case({ReturnValueCondition(WithinRange,
1596957014daSBalázs Kéri                                       {{EOFv, EOFv}, {0, UCharRangeMax}})},
1597957014daSBalázs Kéri                 ErrnoIrrelevant));
1598bba497fbSArtem Dergachev 
1599bba497fbSArtem Dergachev   // read()-like functions that never return more than buffer size.
1600a012bc4cSGabor Marton   auto FreadSummary =
1601a012bc4cSGabor Marton       Summary(NoEvalCall)
1602b40b3196SGabor Marton           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1603957014daSBalázs Kéri                  ReturnValueCondition(WithinRange, Range(0, SizeMax))},
1604957014daSBalázs Kéri                 ErrnoIrrelevant)
1605a012bc4cSGabor Marton           .ArgConstraint(NotNull(ArgNo(0)))
1606a012bc4cSGabor Marton           .ArgConstraint(NotNull(ArgNo(3)))
1607a012bc4cSGabor Marton           .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
1608a012bc4cSGabor Marton                                     /*BufSizeMultiplier=*/ArgNo(2)));
1609a012bc4cSGabor Marton 
1610a012bc4cSGabor Marton   // size_t fread(void *restrict ptr, size_t size, size_t nitems,
1611a012bc4cSGabor Marton   //              FILE *restrict stream);
1612a012bc4cSGabor Marton   addToFunctionSummaryMap(
1613a012bc4cSGabor Marton       "fread",
1614a012bc4cSGabor Marton       Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
1615a012bc4cSGabor Marton                 RetType{SizeTy}),
1616a012bc4cSGabor Marton       FreadSummary);
1617a012bc4cSGabor Marton   // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
1618a012bc4cSGabor Marton   //               FILE *restrict stream);
1619a012bc4cSGabor Marton   addToFunctionSummaryMap("fwrite",
1620a012bc4cSGabor Marton                           Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy,
1621a012bc4cSGabor Marton                                              SizeTy, FilePtrRestrictTy},
1622a012bc4cSGabor Marton                                     RetType{SizeTy}),
1623a012bc4cSGabor Marton                           FreadSummary);
1624634258b8SGabor Marton 
1625d63a945aSGabor Marton   Optional<QualType> Ssize_tTy = lookupTy("ssize_t");
1626d63a945aSGabor Marton   Optional<RangeInt> Ssize_tMax = getMaxValue(Ssize_tTy);
1627d63a945aSGabor Marton 
1628d63a945aSGabor Marton   auto ReadSummary =
1629d63a945aSGabor Marton       Summary(NoEvalCall)
1630d63a945aSGabor Marton           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1631957014daSBalázs Kéri                  ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))},
1632957014daSBalázs Kéri                 ErrnoIrrelevant);
1633d63a945aSGabor Marton 
1634634258b8SGabor Marton   // FIXME these are actually defined by POSIX and not by the C standard, we
1635634258b8SGabor Marton   // should handle them together with the rest of the POSIX functions.
1636d63a945aSGabor Marton   // ssize_t read(int fildes, void *buf, size_t nbyte);
1637d63a945aSGabor Marton   addToFunctionSummaryMap(
1638d63a945aSGabor Marton       "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1639d63a945aSGabor Marton       ReadSummary);
1640d63a945aSGabor Marton   // ssize_t write(int fildes, const void *buf, size_t nbyte);
1641d63a945aSGabor Marton   addToFunctionSummaryMap(
1642d63a945aSGabor Marton       "write",
1643d63a945aSGabor Marton       Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1644d63a945aSGabor Marton       ReadSummary);
1645d63a945aSGabor Marton 
1646d63a945aSGabor Marton   auto GetLineSummary =
1647d63a945aSGabor Marton       Summary(NoEvalCall)
1648d63a945aSGabor Marton           .Case({ReturnValueCondition(WithinRange,
1649957014daSBalázs Kéri                                       Range({-1, -1}, {1, Ssize_tMax}))},
1650957014daSBalázs Kéri                 ErrnoIrrelevant);
1651d63a945aSGabor Marton 
1652d63a945aSGabor Marton   QualType CharPtrPtrRestrictTy = getRestrictTy(getPointerTy(CharPtrTy));
1653634258b8SGabor Marton 
1654bba497fbSArtem Dergachev   // getline()-like functions either fail or read at least the delimiter.
1655634258b8SGabor Marton   // FIXME these are actually defined by POSIX and not by the C standard, we
1656634258b8SGabor Marton   // should handle them together with the rest of the POSIX functions.
1657d63a945aSGabor Marton   // ssize_t getline(char **restrict lineptr, size_t *restrict n,
1658d63a945aSGabor Marton   //                 FILE *restrict stream);
1659d63a945aSGabor Marton   addToFunctionSummaryMap(
1660d63a945aSGabor Marton       "getline",
1661d63a945aSGabor Marton       Signature(
1662d63a945aSGabor Marton           ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, FilePtrRestrictTy},
1663d63a945aSGabor Marton           RetType{Ssize_tTy}),
1664d63a945aSGabor Marton       GetLineSummary);
1665d63a945aSGabor Marton   // ssize_t getdelim(char **restrict lineptr, size_t *restrict n,
1666d63a945aSGabor Marton   //                  int delimiter, FILE *restrict stream);
1667d63a945aSGabor Marton   addToFunctionSummaryMap(
1668d63a945aSGabor Marton       "getdelim",
1669d63a945aSGabor Marton       Signature(ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, IntTy,
1670d63a945aSGabor Marton                          FilePtrRestrictTy},
1671d63a945aSGabor Marton                 RetType{Ssize_tTy}),
1672d63a945aSGabor Marton       GetLineSummary);
16731525232eSGabor Marton 
1674edde4efcSBalazs Benics   {
1675f68c0a2fSArtem Dergachev     Summary GetenvSummary =
1676f68c0a2fSArtem Dergachev         Summary(NoEvalCall)
1677edde4efcSBalazs Benics             .ArgConstraint(NotNull(ArgNo(0)))
1678957014daSBalázs Kéri             .Case({NotNull(Ret)}, ErrnoIrrelevant,
1679957014daSBalázs Kéri                   "Assuming the environment variable exists");
1680edde4efcSBalazs Benics     // In untrusted environments the envvar might not exist.
1681edde4efcSBalazs Benics     if (!ShouldAssumeControlledEnvironment)
1682957014daSBalázs Kéri       GetenvSummary.Case({NotNull(Ret)->negate()}, ErrnoIrrelevant,
1683f68c0a2fSArtem Dergachev                          "Assuming the environment variable does not exist");
1684edde4efcSBalazs Benics 
16857fc15030SBalazs Benics     // char *getenv(const char *name);
16867fc15030SBalazs Benics     addToFunctionSummaryMap(
16877fc15030SBalazs Benics         "getenv", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1688edde4efcSBalazs Benics         std::move(GetenvSummary));
1689edde4efcSBalazs Benics   }
16907fc15030SBalazs Benics 
1691db4d5f70SGabor Marton   if (ModelPOSIX) {
1692db4d5f70SGabor Marton 
1693db4d5f70SGabor Marton     // long a64l(const char *str64);
1694db4d5f70SGabor Marton     addToFunctionSummaryMap(
169511d2e63aSGabor Marton         "a64l", Signature(ArgTypes{ConstCharPtrTy}, RetType{LongTy}),
169611d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1697db4d5f70SGabor Marton 
1698db4d5f70SGabor Marton     // char *l64a(long value);
169911d2e63aSGabor Marton     addToFunctionSummaryMap("l64a",
170011d2e63aSGabor Marton                             Signature(ArgTypes{LongTy}, RetType{CharPtrTy}),
170111d2e63aSGabor Marton                             Summary(NoEvalCall)
170211d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
170311d2e63aSGabor Marton                                     0, WithinRange, Range(0, LongMax))));
1704db4d5f70SGabor Marton 
1705febe7503SGabor Marton     const auto ReturnsZeroOrMinusOne =
1706febe7503SGabor Marton         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
1707957014daSBalázs Kéri     const auto ReturnsZero =
1708957014daSBalázs Kéri         ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(0))};
1709957014daSBalázs Kéri     const auto ReturnsMinusOne =
1710957014daSBalázs Kéri         ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(-1))};
1711957014daSBalázs Kéri     const auto ReturnsNonnegative =
1712957014daSBalázs Kéri         ConstraintSet{ReturnValueCondition(WithinRange, Range(0, IntMax))};
1713febe7503SGabor Marton     const auto ReturnsFileDescriptor =
1714febe7503SGabor Marton         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
1715957014daSBalázs Kéri     const auto &ReturnsValidFileDescriptor = ReturnsNonnegative;
1716febe7503SGabor Marton 
1717db4d5f70SGabor Marton     // int access(const char *pathname, int amode);
171811d2e63aSGabor Marton     addToFunctionSummaryMap(
171911d2e63aSGabor Marton         "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
1720febe7503SGabor Marton         Summary(NoEvalCall)
1721957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1722957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1723febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1724db4d5f70SGabor Marton 
1725db4d5f70SGabor Marton     // int faccessat(int dirfd, const char *pathname, int mode, int flags);
1726db4d5f70SGabor Marton     addToFunctionSummaryMap(
172711d2e63aSGabor Marton         "faccessat",
172811d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
172911d2e63aSGabor Marton                   RetType{IntTy}),
1730febe7503SGabor Marton         Summary(NoEvalCall)
1731957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1732957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1733febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1734db4d5f70SGabor Marton 
1735db4d5f70SGabor Marton     // int dup(int fildes);
1736957014daSBalázs Kéri     addToFunctionSummaryMap(
1737957014daSBalázs Kéri         "dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
173811d2e63aSGabor Marton         Summary(NoEvalCall)
1739957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1740957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1741957014daSBalázs Kéri             .ArgConstraint(
1742957014daSBalázs Kéri                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1743db4d5f70SGabor Marton 
1744db4d5f70SGabor Marton     // int dup2(int fildes1, int filedes2);
1745db4d5f70SGabor Marton     addToFunctionSummaryMap(
174611d2e63aSGabor Marton         "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
174711d2e63aSGabor Marton         Summary(NoEvalCall)
1748957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1749957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1750db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1751db4d5f70SGabor Marton             .ArgConstraint(
1752db4d5f70SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, IntMax))));
1753db4d5f70SGabor Marton 
1754db4d5f70SGabor Marton     // int fdatasync(int fildes);
175511d2e63aSGabor Marton     addToFunctionSummaryMap("fdatasync",
175611d2e63aSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
175711d2e63aSGabor Marton                             Summary(NoEvalCall)
1758957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1759957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
176011d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
176111d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1762db4d5f70SGabor Marton 
1763db4d5f70SGabor Marton     // int fnmatch(const char *pattern, const char *string, int flags);
1764db4d5f70SGabor Marton     addToFunctionSummaryMap(
176511d2e63aSGabor Marton         "fnmatch",
176611d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy},
176711d2e63aSGabor Marton                   RetType{IntTy}),
1768957014daSBalázs Kéri         Summary(NoEvalCall)
1769db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1770db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1771db4d5f70SGabor Marton 
1772db4d5f70SGabor Marton     // int fsync(int fildes);
177311d2e63aSGabor Marton     addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}),
177411d2e63aSGabor Marton                             Summary(NoEvalCall)
1775957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1776957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
177711d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
177811d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
1779db4d5f70SGabor Marton 
1780a787a4edSGabor Marton     Optional<QualType> Off_tTy = lookupTy("off_t");
1781db4d5f70SGabor Marton 
1782db4d5f70SGabor Marton     // int truncate(const char *path, off_t length);
1783a787a4edSGabor Marton     addToFunctionSummaryMap(
1784a787a4edSGabor Marton         "truncate",
178511d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
1786febe7503SGabor Marton         Summary(NoEvalCall)
1787957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1788957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1789febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1790db4d5f70SGabor Marton 
1791db4d5f70SGabor Marton     // int symlink(const char *oldpath, const char *newpath);
179211d2e63aSGabor Marton     addToFunctionSummaryMap(
179311d2e63aSGabor Marton         "symlink",
179411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
179511d2e63aSGabor Marton         Summary(NoEvalCall)
1796957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1797957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1798db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1799db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1800db4d5f70SGabor Marton 
1801db4d5f70SGabor Marton     // int symlinkat(const char *oldpath, int newdirfd, const char *newpath);
1802db4d5f70SGabor Marton     addToFunctionSummaryMap(
1803db4d5f70SGabor Marton         "symlinkat",
180411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
180511d2e63aSGabor Marton                   RetType{IntTy}),
180611d2e63aSGabor Marton         Summary(NoEvalCall)
1807957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1808957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1809db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
1810db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
1811db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
1812db4d5f70SGabor Marton 
1813db4d5f70SGabor Marton     // int lockf(int fd, int cmd, off_t len);
1814db4d5f70SGabor Marton     addToFunctionSummaryMap(
181511d2e63aSGabor Marton         "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}),
181611d2e63aSGabor Marton         Summary(NoEvalCall)
1817957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1818957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1819db4d5f70SGabor Marton             .ArgConstraint(
1820db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1821db4d5f70SGabor Marton 
1822a787a4edSGabor Marton     Optional<QualType> Mode_tTy = lookupTy("mode_t");
1823db4d5f70SGabor Marton 
1824db4d5f70SGabor Marton     // int creat(const char *pathname, mode_t mode);
182511d2e63aSGabor Marton     addToFunctionSummaryMap(
182611d2e63aSGabor Marton         "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1827febe7503SGabor Marton         Summary(NoEvalCall)
1828957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1829957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1830febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1831db4d5f70SGabor Marton 
1832db4d5f70SGabor Marton     // unsigned int sleep(unsigned int seconds);
1833db4d5f70SGabor Marton     addToFunctionSummaryMap(
183411d2e63aSGabor Marton         "sleep", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
183511d2e63aSGabor Marton         Summary(NoEvalCall)
1836db4d5f70SGabor Marton             .ArgConstraint(
1837db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1838db4d5f70SGabor Marton 
1839a787a4edSGabor Marton     Optional<QualType> DirTy = lookupTy("DIR");
1840a787a4edSGabor Marton     Optional<QualType> DirPtrTy = getPointerTy(DirTy);
1841db4d5f70SGabor Marton 
1842db4d5f70SGabor Marton     // int dirfd(DIR *dirp);
1843957014daSBalázs Kéri     addToFunctionSummaryMap(
1844957014daSBalázs Kéri         "dirfd", Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1845febe7503SGabor Marton         Summary(NoEvalCall)
1846957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1847957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1848febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1849db4d5f70SGabor Marton 
1850db4d5f70SGabor Marton     // unsigned int alarm(unsigned int seconds);
1851db4d5f70SGabor Marton     addToFunctionSummaryMap(
185211d2e63aSGabor Marton         "alarm", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
185311d2e63aSGabor Marton         Summary(NoEvalCall)
1854db4d5f70SGabor Marton             .ArgConstraint(
1855db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1856db4d5f70SGabor Marton 
1857db4d5f70SGabor Marton     // int closedir(DIR *dir);
1858febe7503SGabor Marton     addToFunctionSummaryMap("closedir",
1859febe7503SGabor Marton                             Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1860febe7503SGabor Marton                             Summary(NoEvalCall)
1861957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
1862957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1863febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
1864db4d5f70SGabor Marton 
1865db4d5f70SGabor Marton     // char *strdup(const char *s);
186611d2e63aSGabor Marton     addToFunctionSummaryMap(
186711d2e63aSGabor Marton         "strdup", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
186811d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1869db4d5f70SGabor Marton 
1870db4d5f70SGabor Marton     // char *strndup(const char *s, size_t n);
1871db4d5f70SGabor Marton     addToFunctionSummaryMap(
187211d2e63aSGabor Marton         "strndup",
187311d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}),
187411d2e63aSGabor Marton         Summary(NoEvalCall)
1875db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
187611d2e63aSGabor Marton             .ArgConstraint(
187711d2e63aSGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1878db4d5f70SGabor Marton 
1879db4d5f70SGabor Marton     // wchar_t *wcsdup(const wchar_t *s);
188011d2e63aSGabor Marton     addToFunctionSummaryMap(
188111d2e63aSGabor Marton         "wcsdup", Signature(ArgTypes{ConstWchar_tPtrTy}, RetType{Wchar_tPtrTy}),
188211d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1883db4d5f70SGabor Marton 
1884db4d5f70SGabor Marton     // int mkstemp(char *template);
1885957014daSBalázs Kéri     addToFunctionSummaryMap(
1886957014daSBalázs Kéri         "mkstemp", Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
1887febe7503SGabor Marton         Summary(NoEvalCall)
1888957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
1889957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1890febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1891db4d5f70SGabor Marton 
1892db4d5f70SGabor Marton     // char *mkdtemp(char *template);
1893957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
1894db4d5f70SGabor Marton     addToFunctionSummaryMap(
189511d2e63aSGabor Marton         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
189611d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1897db4d5f70SGabor Marton 
1898db4d5f70SGabor Marton     // char *getcwd(char *buf, size_t size);
1899957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
1900db4d5f70SGabor Marton     addToFunctionSummaryMap(
190111d2e63aSGabor Marton         "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
190211d2e63aSGabor Marton         Summary(NoEvalCall)
1903db4d5f70SGabor Marton             .ArgConstraint(
1904db4d5f70SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1905db4d5f70SGabor Marton 
1906db4d5f70SGabor Marton     // int mkdir(const char *pathname, mode_t mode);
190711d2e63aSGabor Marton     addToFunctionSummaryMap(
190811d2e63aSGabor Marton         "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1909febe7503SGabor Marton         Summary(NoEvalCall)
19107dc81c62SBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1911957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1912febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1913db4d5f70SGabor Marton 
1914db4d5f70SGabor Marton     // int mkdirat(int dirfd, const char *pathname, mode_t mode);
191511d2e63aSGabor Marton     addToFunctionSummaryMap(
191611d2e63aSGabor Marton         "mkdirat",
191711d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1918febe7503SGabor Marton         Summary(NoEvalCall)
19197dc81c62SBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1920957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1921febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1922db4d5f70SGabor Marton 
1923a787a4edSGabor Marton     Optional<QualType> Dev_tTy = lookupTy("dev_t");
1924db4d5f70SGabor Marton 
1925db4d5f70SGabor Marton     // int mknod(const char *pathname, mode_t mode, dev_t dev);
192611d2e63aSGabor Marton     addToFunctionSummaryMap(
192711d2e63aSGabor Marton         "mknod",
192811d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}),
1929febe7503SGabor Marton         Summary(NoEvalCall)
19307dc81c62SBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1931957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1932febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1933db4d5f70SGabor Marton 
1934db4d5f70SGabor Marton     // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
1935a787a4edSGabor Marton     addToFunctionSummaryMap(
193611d2e63aSGabor Marton         "mknodat",
193711d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy},
193811d2e63aSGabor Marton                   RetType{IntTy}),
1939febe7503SGabor Marton         Summary(NoEvalCall)
19407dc81c62SBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1941957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1942febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1943db4d5f70SGabor Marton 
1944db4d5f70SGabor Marton     // int chmod(const char *path, mode_t mode);
194511d2e63aSGabor Marton     addToFunctionSummaryMap(
194611d2e63aSGabor Marton         "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1947febe7503SGabor Marton         Summary(NoEvalCall)
1948957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1949957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1950febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1951db4d5f70SGabor Marton 
1952db4d5f70SGabor Marton     // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
1953db4d5f70SGabor Marton     addToFunctionSummaryMap(
1954a787a4edSGabor Marton         "fchmodat",
195511d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy},
195611d2e63aSGabor Marton                   RetType{IntTy}),
195711d2e63aSGabor Marton         Summary(NoEvalCall)
1958957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1959957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1960a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1961db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1962db4d5f70SGabor Marton 
1963db4d5f70SGabor Marton     // int fchmod(int fildes, mode_t mode);
1964db4d5f70SGabor Marton     addToFunctionSummaryMap(
196511d2e63aSGabor Marton         "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}),
196611d2e63aSGabor Marton         Summary(NoEvalCall)
1967957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1968957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1969db4d5f70SGabor Marton             .ArgConstraint(
1970db4d5f70SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1971db4d5f70SGabor Marton 
1972a787a4edSGabor Marton     Optional<QualType> Uid_tTy = lookupTy("uid_t");
1973a787a4edSGabor Marton     Optional<QualType> Gid_tTy = lookupTy("gid_t");
1974db4d5f70SGabor Marton 
1975db4d5f70SGabor Marton     // int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group,
1976db4d5f70SGabor Marton     //              int flags);
1977db4d5f70SGabor Marton     addToFunctionSummaryMap(
1978db4d5f70SGabor Marton         "fchownat",
197911d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy},
198011d2e63aSGabor Marton                   RetType{IntTy}),
198111d2e63aSGabor Marton         Summary(NoEvalCall)
1982957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1983957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1984a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1985db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
1986db4d5f70SGabor Marton 
1987db4d5f70SGabor Marton     // int chown(const char *path, uid_t owner, gid_t group);
198811d2e63aSGabor Marton     addToFunctionSummaryMap(
198911d2e63aSGabor Marton         "chown",
199011d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1991febe7503SGabor Marton         Summary(NoEvalCall)
1992957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
1993957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
1994febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
1995db4d5f70SGabor Marton 
1996db4d5f70SGabor Marton     // int lchown(const char *path, uid_t owner, gid_t group);
199711d2e63aSGabor Marton     addToFunctionSummaryMap(
199811d2e63aSGabor Marton         "lchown",
199911d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
2000febe7503SGabor Marton         Summary(NoEvalCall)
2001957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2002957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2003febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2004db4d5f70SGabor Marton 
2005db4d5f70SGabor Marton     // int fchown(int fildes, uid_t owner, gid_t group);
2006db4d5f70SGabor Marton     addToFunctionSummaryMap(
200711d2e63aSGabor Marton         "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
200811d2e63aSGabor Marton         Summary(NoEvalCall)
2009957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2010957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2011a787a4edSGabor Marton             .ArgConstraint(
2012a787a4edSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2013db4d5f70SGabor Marton 
2014db4d5f70SGabor Marton     // int rmdir(const char *pathname);
2015febe7503SGabor Marton     addToFunctionSummaryMap("rmdir",
2016febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
2017febe7503SGabor Marton                             Summary(NoEvalCall)
2018957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2019957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2020febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
2021db4d5f70SGabor Marton 
2022db4d5f70SGabor Marton     // int chdir(const char *path);
2023febe7503SGabor Marton     addToFunctionSummaryMap("chdir",
2024febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
2025febe7503SGabor Marton                             Summary(NoEvalCall)
2026957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2027957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2028febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
2029db4d5f70SGabor Marton 
2030db4d5f70SGabor Marton     // int link(const char *oldpath, const char *newpath);
203111d2e63aSGabor Marton     addToFunctionSummaryMap(
203211d2e63aSGabor Marton         "link",
203311d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
203411d2e63aSGabor Marton         Summary(NoEvalCall)
2035957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2036957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2037db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2038db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2039db4d5f70SGabor Marton 
2040db4d5f70SGabor Marton     // int linkat(int fd1, const char *path1, int fd2, const char *path2,
2041db4d5f70SGabor Marton     //            int flag);
2042db4d5f70SGabor Marton     addToFunctionSummaryMap(
2043db4d5f70SGabor Marton         "linkat",
204411d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy},
204511d2e63aSGabor Marton                   RetType{IntTy}),
204611d2e63aSGabor Marton         Summary(NoEvalCall)
2047957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2048957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2049db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2050db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2051db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
2052db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
2053db4d5f70SGabor Marton 
2054db4d5f70SGabor Marton     // int unlink(const char *pathname);
2055febe7503SGabor Marton     addToFunctionSummaryMap("unlink",
2056febe7503SGabor Marton                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
2057febe7503SGabor Marton                             Summary(NoEvalCall)
2058957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2059957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2060febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
2061db4d5f70SGabor Marton 
2062db4d5f70SGabor Marton     // int unlinkat(int fd, const char *path, int flag);
2063db4d5f70SGabor Marton     addToFunctionSummaryMap(
2064db4d5f70SGabor Marton         "unlinkat",
206511d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}),
206611d2e63aSGabor Marton         Summary(NoEvalCall)
2067957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2068957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2069db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2070db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2071db4d5f70SGabor Marton 
2072a787a4edSGabor Marton     Optional<QualType> StructStatTy = lookupTy("stat");
2073a787a4edSGabor Marton     Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy);
2074a787a4edSGabor Marton     Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy);
2075db4d5f70SGabor Marton 
2076db4d5f70SGabor Marton     // int fstat(int fd, struct stat *statbuf);
2077db4d5f70SGabor Marton     addToFunctionSummaryMap(
207811d2e63aSGabor Marton         "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}),
207911d2e63aSGabor Marton         Summary(NoEvalCall)
2080957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2081957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2082a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2083db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2084db4d5f70SGabor Marton 
2085db4d5f70SGabor Marton     // int stat(const char *restrict path, struct stat *restrict buf);
208611d2e63aSGabor Marton     addToFunctionSummaryMap(
208711d2e63aSGabor Marton         "stat",
208811d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
208911d2e63aSGabor Marton                   RetType{IntTy}),
209011d2e63aSGabor Marton         Summary(NoEvalCall)
2091957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2092957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2093db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2094db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2095db4d5f70SGabor Marton 
2096db4d5f70SGabor Marton     // int lstat(const char *restrict path, struct stat *restrict buf);
209711d2e63aSGabor Marton     addToFunctionSummaryMap(
209811d2e63aSGabor Marton         "lstat",
209911d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
210011d2e63aSGabor Marton                   RetType{IntTy}),
210111d2e63aSGabor Marton         Summary(NoEvalCall)
2102957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2103957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2104db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2105db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2106db4d5f70SGabor Marton 
2107db4d5f70SGabor Marton     // int fstatat(int fd, const char *restrict path,
2108db4d5f70SGabor Marton     //             struct stat *restrict buf, int flag);
2109db4d5f70SGabor Marton     addToFunctionSummaryMap(
2110a787a4edSGabor Marton         "fstatat",
211111d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy,
211211d2e63aSGabor Marton                            StructStatPtrRestrictTy, IntTy},
211311d2e63aSGabor Marton                   RetType{IntTy}),
211411d2e63aSGabor Marton         Summary(NoEvalCall)
2115957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2116957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2117a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2118db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2119db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
2120db4d5f70SGabor Marton 
2121db4d5f70SGabor Marton     // DIR *opendir(const char *name);
2122957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
212311d2e63aSGabor Marton     addToFunctionSummaryMap(
212411d2e63aSGabor Marton         "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
212511d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2126db4d5f70SGabor Marton 
2127db4d5f70SGabor Marton     // DIR *fdopendir(int fd);
2128957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
212911d2e63aSGabor Marton     addToFunctionSummaryMap("fdopendir",
213011d2e63aSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
213111d2e63aSGabor Marton                             Summary(NoEvalCall)
213211d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
213311d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
2134db4d5f70SGabor Marton 
2135db4d5f70SGabor Marton     // int isatty(int fildes);
2136febe7503SGabor Marton     addToFunctionSummaryMap(
2137febe7503SGabor Marton         "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}),
213811d2e63aSGabor Marton         Summary(NoEvalCall)
2139957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, Range(0, 1))},
2140957014daSBalázs Kéri                   ErrnoIrrelevant)
2141febe7503SGabor Marton             .ArgConstraint(
2142febe7503SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2143db4d5f70SGabor Marton 
2144db4d5f70SGabor Marton     // FILE *popen(const char *command, const char *type);
2145957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
214611d2e63aSGabor Marton     addToFunctionSummaryMap(
214711d2e63aSGabor Marton         "popen",
214811d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}),
214911d2e63aSGabor Marton         Summary(NoEvalCall)
2150db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2151db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2152db4d5f70SGabor Marton 
2153db4d5f70SGabor Marton     // int pclose(FILE *stream);
2154957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
2155db4d5f70SGabor Marton     addToFunctionSummaryMap(
215611d2e63aSGabor Marton         "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
215711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2158db4d5f70SGabor Marton 
2159db4d5f70SGabor Marton     // int close(int fildes);
216011d2e63aSGabor Marton     addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}),
216111d2e63aSGabor Marton                             Summary(NoEvalCall)
2162957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2163957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
216411d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
2165d14c6316SGabor Marton                                     0, WithinRange, Range(-1, IntMax))));
2166db4d5f70SGabor Marton 
2167db4d5f70SGabor Marton     // long fpathconf(int fildes, int name);
216811d2e63aSGabor Marton     addToFunctionSummaryMap("fpathconf",
216911d2e63aSGabor Marton                             Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}),
217011d2e63aSGabor Marton                             Summary(NoEvalCall)
217111d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
217211d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
2173db4d5f70SGabor Marton 
2174db4d5f70SGabor Marton     // long pathconf(const char *path, int name);
217511d2e63aSGabor Marton     addToFunctionSummaryMap(
217611d2e63aSGabor Marton         "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}),
217711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2178db4d5f70SGabor Marton 
2179db4d5f70SGabor Marton     // FILE *fdopen(int fd, const char *mode);
2180957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
2181db4d5f70SGabor Marton     addToFunctionSummaryMap(
2182a787a4edSGabor Marton         "fdopen",
218311d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}),
218411d2e63aSGabor Marton         Summary(NoEvalCall)
2185a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2186db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2187db4d5f70SGabor Marton 
2188db4d5f70SGabor Marton     // void rewinddir(DIR *dir);
2189db4d5f70SGabor Marton     addToFunctionSummaryMap(
219011d2e63aSGabor Marton         "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}),
219111d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2192db4d5f70SGabor Marton 
2193db4d5f70SGabor Marton     // void seekdir(DIR *dirp, long loc);
219411d2e63aSGabor Marton     addToFunctionSummaryMap(
219511d2e63aSGabor Marton         "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}),
219611d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2197db4d5f70SGabor Marton 
2198db4d5f70SGabor Marton     // int rand_r(unsigned int *seedp);
219911d2e63aSGabor Marton     addToFunctionSummaryMap(
220011d2e63aSGabor Marton         "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}),
220111d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2202db4d5f70SGabor Marton 
2203db4d5f70SGabor Marton     // int fileno(FILE *stream);
2204957014daSBalázs Kéri     addToFunctionSummaryMap(
2205957014daSBalázs Kéri         "fileno", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
2206febe7503SGabor Marton         Summary(NoEvalCall)
2207957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
2208957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2209febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2210db4d5f70SGabor Marton 
2211db4d5f70SGabor Marton     // int fseeko(FILE *stream, off_t offset, int whence);
2212a787a4edSGabor Marton     addToFunctionSummaryMap(
2213a787a4edSGabor Marton         "fseeko",
221411d2e63aSGabor Marton         Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
2215febe7503SGabor Marton         Summary(NoEvalCall)
2216957014daSBalázs Kéri             .Case(ReturnsZeroOrMinusOne, ErrnoIrrelevant)
2217febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2218db4d5f70SGabor Marton 
2219db4d5f70SGabor Marton     // off_t ftello(FILE *stream);
2220db4d5f70SGabor Marton     addToFunctionSummaryMap(
222111d2e63aSGabor Marton         "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
222211d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2223db4d5f70SGabor Marton 
2224db4d5f70SGabor Marton     // void *mmap(void *addr, size_t length, int prot, int flags, int fd,
2225db4d5f70SGabor Marton     // off_t offset);
2226957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
2227db4d5f70SGabor Marton     addToFunctionSummaryMap(
2228db4d5f70SGabor Marton         "mmap",
222911d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
223011d2e63aSGabor Marton                   RetType{VoidPtrTy}),
223111d2e63aSGabor Marton         Summary(NoEvalCall)
2232a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
2233db4d5f70SGabor Marton             .ArgConstraint(
2234d14c6316SGabor Marton                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
2235db4d5f70SGabor Marton 
2236a787a4edSGabor Marton     Optional<QualType> Off64_tTy = lookupTy("off64_t");
2237db4d5f70SGabor Marton     // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
2238db4d5f70SGabor Marton     // off64_t offset);
2239957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
2240db4d5f70SGabor Marton     addToFunctionSummaryMap(
2241db4d5f70SGabor Marton         "mmap64",
224211d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
224311d2e63aSGabor Marton                   RetType{VoidPtrTy}),
224411d2e63aSGabor Marton         Summary(NoEvalCall)
2245a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
2246db4d5f70SGabor Marton             .ArgConstraint(
2247d14c6316SGabor Marton                 ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
2248db4d5f70SGabor Marton 
2249db4d5f70SGabor Marton     // int pipe(int fildes[2]);
2250febe7503SGabor Marton     addToFunctionSummaryMap("pipe",
2251febe7503SGabor Marton                             Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2252febe7503SGabor Marton                             Summary(NoEvalCall)
2253957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2254957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2255febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(0))));
2256db4d5f70SGabor Marton 
2257db4d5f70SGabor Marton     // off_t lseek(int fildes, off_t offset, int whence);
2258957014daSBalázs Kéri     // In the first case we can not tell for sure if it failed or not.
2259957014daSBalázs Kéri     // A return value different from of the expected offset (that is unknown
2260957014daSBalázs Kéri     // here) may indicate failure. For this reason we do not enforce the errno
2261957014daSBalázs Kéri     // check (can cause false positive).
2262db4d5f70SGabor Marton     addToFunctionSummaryMap(
226311d2e63aSGabor Marton         "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}),
226411d2e63aSGabor Marton         Summary(NoEvalCall)
2265957014daSBalázs Kéri             .Case(ReturnsNonnegative, ErrnoIrrelevant)
2266957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2267a787a4edSGabor Marton             .ArgConstraint(
2268a787a4edSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2269db4d5f70SGabor Marton 
2270db4d5f70SGabor Marton     // ssize_t readlink(const char *restrict path, char *restrict buf,
2271db4d5f70SGabor Marton     //                  size_t bufsize);
2272db4d5f70SGabor Marton     addToFunctionSummaryMap(
2273db4d5f70SGabor Marton         "readlink",
227411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
227511d2e63aSGabor Marton                   RetType{Ssize_tTy}),
227611d2e63aSGabor Marton         Summary(NoEvalCall)
2277b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2278957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2279957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2280957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2281db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2282db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2283db4d5f70SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2284db4d5f70SGabor Marton                                       /*BufSize=*/ArgNo(2)))
2285db4d5f70SGabor Marton             .ArgConstraint(
2286db4d5f70SGabor Marton                 ArgumentCondition(2, WithinRange, Range(0, SizeMax))));
2287db4d5f70SGabor Marton 
2288db4d5f70SGabor Marton     // ssize_t readlinkat(int fd, const char *restrict path,
2289db4d5f70SGabor Marton     //                    char *restrict buf, size_t bufsize);
2290db4d5f70SGabor Marton     addToFunctionSummaryMap(
2291a787a4edSGabor Marton         "readlinkat",
229211d2e63aSGabor Marton         Signature(
2293a787a4edSGabor Marton             ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
229411d2e63aSGabor Marton             RetType{Ssize_tTy}),
229511d2e63aSGabor Marton         Summary(NoEvalCall)
2296b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
2297957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2298957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2299957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2300a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2301db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2302db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2)))
2303db4d5f70SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
2304db4d5f70SGabor Marton                                       /*BufSize=*/ArgNo(3)))
2305a787a4edSGabor Marton             .ArgConstraint(
2306a787a4edSGabor Marton                 ArgumentCondition(3, WithinRange, Range(0, SizeMax))));
2307db4d5f70SGabor Marton 
2308db4d5f70SGabor Marton     // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char
2309db4d5f70SGabor Marton     // *newpath);
231011d2e63aSGabor Marton     addToFunctionSummaryMap(
231111d2e63aSGabor Marton         "renameat",
231211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy},
231311d2e63aSGabor Marton                   RetType{IntTy}),
231411d2e63aSGabor Marton         Summary(NoEvalCall)
2315957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2316957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2317db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2318db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
2319db4d5f70SGabor Marton 
2320db4d5f70SGabor Marton     // char *realpath(const char *restrict file_name,
2321db4d5f70SGabor Marton     //                char *restrict resolved_name);
2322957014daSBalázs Kéri     // FIXME: Improve for errno modeling.
2323db4d5f70SGabor Marton     addToFunctionSummaryMap(
232411d2e63aSGabor Marton         "realpath",
232511d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
232611d2e63aSGabor Marton                   RetType{CharPtrTy}),
232711d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2328db4d5f70SGabor Marton 
2329a787a4edSGabor Marton     QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy));
2330db4d5f70SGabor Marton 
2331db4d5f70SGabor Marton     // int execv(const char *path, char *const argv[]);
233211d2e63aSGabor Marton     addToFunctionSummaryMap(
233311d2e63aSGabor Marton         "execv",
233411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2335febe7503SGabor Marton         Summary(NoEvalCall)
2336957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
2337957014daSBalázs Kéri                   ErrnoIrrelevant)
2338febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2339db4d5f70SGabor Marton 
2340db4d5f70SGabor Marton     // int execvp(const char *file, char *const argv[]);
234111d2e63aSGabor Marton     addToFunctionSummaryMap(
234211d2e63aSGabor Marton         "execvp",
234311d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2344febe7503SGabor Marton         Summary(NoEvalCall)
2345957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
2346957014daSBalázs Kéri                   ErrnoIrrelevant)
2347febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2348db4d5f70SGabor Marton 
2349db4d5f70SGabor Marton     // int getopt(int argc, char * const argv[], const char *optstring);
2350db4d5f70SGabor Marton     addToFunctionSummaryMap(
2351db4d5f70SGabor Marton         "getopt",
235211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
235311d2e63aSGabor Marton                   RetType{IntTy}),
235411d2e63aSGabor Marton         Summary(NoEvalCall)
2355957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))},
2356957014daSBalázs Kéri                   ErrnoIrrelevant)
2357db4d5f70SGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2358db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2359db4d5f70SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
23603ff220deSGabor Marton 
2361a787a4edSGabor Marton     Optional<QualType> StructSockaddrTy = lookupTy("sockaddr");
2362a787a4edSGabor Marton     Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy);
2363a787a4edSGabor Marton     Optional<QualType> ConstStructSockaddrPtrTy =
2364a787a4edSGabor Marton         getPointerTy(getConstTy(StructSockaddrTy));
2365a787a4edSGabor Marton     Optional<QualType> StructSockaddrPtrRestrictTy =
2366a787a4edSGabor Marton         getRestrictTy(StructSockaddrPtrTy);
2367a787a4edSGabor Marton     Optional<QualType> ConstStructSockaddrPtrRestrictTy =
2368a787a4edSGabor Marton         getRestrictTy(ConstStructSockaddrPtrTy);
2369a787a4edSGabor Marton     Optional<QualType> Socklen_tTy = lookupTy("socklen_t");
2370a787a4edSGabor Marton     Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy);
2371a787a4edSGabor Marton     Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
2372a787a4edSGabor Marton     Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy);
23733ff220deSGabor Marton 
23743ff220deSGabor Marton     // In 'socket.h' of some libc implementations with C99, sockaddr parameter
23753ff220deSGabor Marton     // is a transparent union of the underlying sockaddr_ family of pointers
23763ff220deSGabor Marton     // instead of being a pointer to struct sockaddr. In these cases, the
23773ff220deSGabor Marton     // standardized signature will not match, thus we try to match with another
23783ff220deSGabor Marton     // signature that has the joker Irrelevant type. We also remove those
23793ff220deSGabor Marton     // constraints which require pointer types for the sockaddr param.
2380a787a4edSGabor Marton     auto Accept =
2381a787a4edSGabor Marton         Summary(NoEvalCall)
2382957014daSBalázs Kéri             .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
2383957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2384a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
23853ff220deSGabor Marton     if (!addToFunctionSummaryMap(
23863ff220deSGabor Marton             "accept",
23873ff220deSGabor Marton             // int accept(int socket, struct sockaddr *restrict address,
23883ff220deSGabor Marton             //            socklen_t *restrict address_len);
2389a787a4edSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2390a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
23913ff220deSGabor Marton                       RetType{IntTy}),
23923ff220deSGabor Marton             Accept))
23933ff220deSGabor Marton       addToFunctionSummaryMap(
23943ff220deSGabor Marton           "accept",
2395a787a4edSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
23963ff220deSGabor Marton                     RetType{IntTy}),
23973ff220deSGabor Marton           Accept);
23983ff220deSGabor Marton 
23993ff220deSGabor Marton     // int bind(int socket, const struct sockaddr *address, socklen_t
24003ff220deSGabor Marton     //          address_len);
24013ff220deSGabor Marton     if (!addToFunctionSummaryMap(
24023ff220deSGabor Marton             "bind",
240311d2e63aSGabor Marton             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
240411d2e63aSGabor Marton                       RetType{IntTy}),
240511d2e63aSGabor Marton             Summary(NoEvalCall)
2406957014daSBalázs Kéri                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2407957014daSBalázs Kéri                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
24083ff220deSGabor Marton                 .ArgConstraint(
24093ff220deSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
24103ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
24113ff220deSGabor Marton                 .ArgConstraint(
24123ff220deSGabor Marton                     BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))
2413a787a4edSGabor Marton                 .ArgConstraint(
2414a787a4edSGabor Marton                     ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))))
24153ff220deSGabor Marton       // Do not add constraints on sockaddr.
24163ff220deSGabor Marton       addToFunctionSummaryMap(
241711d2e63aSGabor Marton           "bind",
241811d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
241911d2e63aSGabor Marton           Summary(NoEvalCall)
2420957014daSBalázs Kéri               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2421957014daSBalázs Kéri               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
24223ff220deSGabor Marton               .ArgConstraint(
24233ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax)))
242411d2e63aSGabor Marton               .ArgConstraint(
242511d2e63aSGabor Marton                   ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))));
24263ff220deSGabor Marton 
24273ff220deSGabor Marton     // int getpeername(int socket, struct sockaddr *restrict address,
24283ff220deSGabor Marton     //                 socklen_t *restrict address_len);
24293ff220deSGabor Marton     if (!addToFunctionSummaryMap(
243011d2e63aSGabor Marton             "getpeername",
243111d2e63aSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2432a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
243311d2e63aSGabor Marton                       RetType{IntTy}),
243411d2e63aSGabor Marton             Summary(NoEvalCall)
2435957014daSBalázs Kéri                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2436957014daSBalázs Kéri                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
243711d2e63aSGabor Marton                 .ArgConstraint(
243811d2e63aSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
24393ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
24403ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(2)))))
24413ff220deSGabor Marton       addToFunctionSummaryMap(
24423ff220deSGabor Marton           "getpeername",
244311d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
244411d2e63aSGabor Marton                     RetType{IntTy}),
244511d2e63aSGabor Marton           Summary(NoEvalCall)
2446957014daSBalázs Kéri               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2447957014daSBalázs Kéri               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
24483ff220deSGabor Marton               .ArgConstraint(
24493ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
24503ff220deSGabor Marton 
24513ff220deSGabor Marton     // int getsockname(int socket, struct sockaddr *restrict address,
24523ff220deSGabor Marton     //                 socklen_t *restrict address_len);
24533ff220deSGabor Marton     if (!addToFunctionSummaryMap(
245411d2e63aSGabor Marton             "getsockname",
245511d2e63aSGabor Marton             Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2456a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
245711d2e63aSGabor Marton                       RetType{IntTy}),
245811d2e63aSGabor Marton             Summary(NoEvalCall)
2459957014daSBalázs Kéri                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2460957014daSBalázs Kéri                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
246111d2e63aSGabor Marton                 .ArgConstraint(
246211d2e63aSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
24633ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))
24643ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(2)))))
24653ff220deSGabor Marton       addToFunctionSummaryMap(
24663ff220deSGabor Marton           "getsockname",
246711d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
246811d2e63aSGabor Marton                     RetType{IntTy}),
246911d2e63aSGabor Marton           Summary(NoEvalCall)
2470957014daSBalázs Kéri               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2471957014daSBalázs Kéri               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
24723ff220deSGabor Marton               .ArgConstraint(
24733ff220deSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
24743ff220deSGabor Marton 
24753ff220deSGabor Marton     // int connect(int socket, const struct sockaddr *address, socklen_t
24763ff220deSGabor Marton     //             address_len);
24773ff220deSGabor Marton     if (!addToFunctionSummaryMap(
24783ff220deSGabor Marton             "connect",
247911d2e63aSGabor Marton             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
248011d2e63aSGabor Marton                       RetType{IntTy}),
248111d2e63aSGabor Marton             Summary(NoEvalCall)
2482957014daSBalázs Kéri                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2483957014daSBalázs Kéri                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
24843ff220deSGabor Marton                 .ArgConstraint(
24853ff220deSGabor Marton                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
24863ff220deSGabor Marton                 .ArgConstraint(NotNull(ArgNo(1)))))
24873ff220deSGabor Marton       addToFunctionSummaryMap(
248811d2e63aSGabor Marton           "connect",
248911d2e63aSGabor Marton           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
249011d2e63aSGabor Marton           Summary(NoEvalCall)
2491957014daSBalázs Kéri               .Case(ReturnsZero, ErrnoMustNotBeChecked)
2492957014daSBalázs Kéri               .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
249311d2e63aSGabor Marton               .ArgConstraint(
249411d2e63aSGabor Marton                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
24953ff220deSGabor Marton 
2496a787a4edSGabor Marton     auto Recvfrom =
2497a787a4edSGabor Marton         Summary(NoEvalCall)
2498b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2499957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2500957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2501957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2502a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
25033ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
25043ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2)));
2505a787a4edSGabor Marton     if (!addToFunctionSummaryMap(
25063ff220deSGabor Marton             "recvfrom",
25073ff220deSGabor Marton             // ssize_t recvfrom(int socket, void *restrict buffer,
25083ff220deSGabor Marton             //                  size_t length,
25093ff220deSGabor Marton             //                  int flags, struct sockaddr *restrict address,
25103ff220deSGabor Marton             //                  socklen_t *restrict address_len);
25113ff220deSGabor Marton             Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2512a787a4edSGabor Marton                                StructSockaddrPtrRestrictTy,
2513a787a4edSGabor Marton                                Socklen_tPtrRestrictTy},
2514a787a4edSGabor Marton                       RetType{Ssize_tTy}),
25153ff220deSGabor Marton             Recvfrom))
25163ff220deSGabor Marton       addToFunctionSummaryMap(
25173ff220deSGabor Marton           "recvfrom",
25183ff220deSGabor Marton           Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2519a787a4edSGabor Marton                              Irrelevant, Socklen_tPtrRestrictTy},
2520a787a4edSGabor Marton                     RetType{Ssize_tTy}),
25213ff220deSGabor Marton           Recvfrom);
25223ff220deSGabor Marton 
2523a787a4edSGabor Marton     auto Sendto =
2524a787a4edSGabor Marton         Summary(NoEvalCall)
2525b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2526957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2527957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2528957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2529a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
25303ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
25313ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2)));
2532a787a4edSGabor Marton     if (!addToFunctionSummaryMap(
25333ff220deSGabor Marton             "sendto",
25343ff220deSGabor Marton             // ssize_t sendto(int socket, const void *message, size_t length,
25353ff220deSGabor Marton             //                int flags, const struct sockaddr *dest_addr,
25363ff220deSGabor Marton             //                socklen_t dest_len);
25373ff220deSGabor Marton             Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy,
2538a787a4edSGabor Marton                                ConstStructSockaddrPtrTy, Socklen_tTy},
2539a787a4edSGabor Marton                       RetType{Ssize_tTy}),
25403ff220deSGabor Marton             Sendto))
25413ff220deSGabor Marton       addToFunctionSummaryMap(
25423ff220deSGabor Marton           "sendto",
25433ff220deSGabor Marton           Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant,
2544a787a4edSGabor Marton                              Socklen_tTy},
2545a787a4edSGabor Marton                     RetType{Ssize_tTy}),
25463ff220deSGabor Marton           Sendto);
25473ff220deSGabor Marton 
25483ff220deSGabor Marton     // int listen(int sockfd, int backlog);
254911d2e63aSGabor Marton     addToFunctionSummaryMap("listen",
255011d2e63aSGabor Marton                             Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
255111d2e63aSGabor Marton                             Summary(NoEvalCall)
2552957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2553957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
255411d2e63aSGabor Marton                                 .ArgConstraint(ArgumentCondition(
255511d2e63aSGabor Marton                                     0, WithinRange, Range(0, IntMax))));
25563ff220deSGabor Marton 
25573ff220deSGabor Marton     // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
25583ff220deSGabor Marton     addToFunctionSummaryMap(
2559a787a4edSGabor Marton         "recv",
256011d2e63aSGabor Marton         Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy},
256111d2e63aSGabor Marton                   RetType{Ssize_tTy}),
256211d2e63aSGabor Marton         Summary(NoEvalCall)
2563b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2564957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2565957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2566957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2567a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
25683ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
25693ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2))));
25703ff220deSGabor Marton 
2571a787a4edSGabor Marton     Optional<QualType> StructMsghdrTy = lookupTy("msghdr");
2572a787a4edSGabor Marton     Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy);
2573a787a4edSGabor Marton     Optional<QualType> ConstStructMsghdrPtrTy =
2574a787a4edSGabor Marton         getPointerTy(getConstTy(StructMsghdrTy));
25753ff220deSGabor Marton 
25763ff220deSGabor Marton     // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
2577b40b3196SGabor Marton     addToFunctionSummaryMap(
2578b40b3196SGabor Marton         "recvmsg",
257911d2e63aSGabor Marton         Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
258011d2e63aSGabor Marton                   RetType{Ssize_tTy}),
258111d2e63aSGabor Marton         Summary(NoEvalCall)
2582957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2583957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2584957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2585b40b3196SGabor Marton             .ArgConstraint(
2586b40b3196SGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
25873ff220deSGabor Marton 
25883ff220deSGabor Marton     // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
25893ff220deSGabor Marton     addToFunctionSummaryMap(
259011d2e63aSGabor Marton         "sendmsg",
259111d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
259211d2e63aSGabor Marton                   RetType{Ssize_tTy}),
259311d2e63aSGabor Marton         Summary(NoEvalCall)
2594957014daSBalázs Kéri             .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2595957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2596957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
259711d2e63aSGabor Marton             .ArgConstraint(
259811d2e63aSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
25993ff220deSGabor Marton 
26003ff220deSGabor Marton     // int setsockopt(int socket, int level, int option_name,
26013ff220deSGabor Marton     //                const void *option_value, socklen_t option_len);
26023ff220deSGabor Marton     addToFunctionSummaryMap(
26033ff220deSGabor Marton         "setsockopt",
260411d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
260511d2e63aSGabor Marton                   RetType{IntTy}),
260611d2e63aSGabor Marton         Summary(NoEvalCall)
2607957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2608957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
26093ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(3)))
26103ff220deSGabor Marton             .ArgConstraint(
26113ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
26123ff220deSGabor Marton             .ArgConstraint(
2613a787a4edSGabor Marton                 ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax))));
26143ff220deSGabor Marton 
26153ff220deSGabor Marton     // int getsockopt(int socket, int level, int option_name,
26163ff220deSGabor Marton     //                void *restrict option_value,
26173ff220deSGabor Marton     //                socklen_t *restrict option_len);
26183ff220deSGabor Marton     addToFunctionSummaryMap(
261911d2e63aSGabor Marton         "getsockopt",
262011d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy,
2621a787a4edSGabor Marton                            Socklen_tPtrRestrictTy},
262211d2e63aSGabor Marton                   RetType{IntTy}),
262311d2e63aSGabor Marton         Summary(NoEvalCall)
2624957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2625957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
26263ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(3)))
26273ff220deSGabor Marton             .ArgConstraint(NotNull(ArgNo(4))));
26283ff220deSGabor Marton 
26293ff220deSGabor Marton     // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
26303ff220deSGabor Marton     addToFunctionSummaryMap(
2631a787a4edSGabor Marton         "send",
263211d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy},
263311d2e63aSGabor Marton                   RetType{Ssize_tTy}),
263411d2e63aSGabor Marton         Summary(NoEvalCall)
2635b40b3196SGabor Marton             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2636957014daSBalázs Kéri                    ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
2637957014daSBalázs Kéri                   ErrnoMustNotBeChecked)
2638957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2639a787a4edSGabor Marton             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
26403ff220deSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
26413ff220deSGabor Marton                                       /*BufSize=*/ArgNo(2))));
26423ff220deSGabor Marton 
26433ff220deSGabor Marton     // int socketpair(int domain, int type, int protocol, int sv[2]);
264411d2e63aSGabor Marton     addToFunctionSummaryMap(
264511d2e63aSGabor Marton         "socketpair",
264611d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}),
2647b40b3196SGabor Marton         Summary(NoEvalCall)
2648957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2649957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2650b40b3196SGabor Marton             .ArgConstraint(NotNull(ArgNo(3))));
26513ff220deSGabor Marton 
26523ff220deSGabor Marton     // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
26533ff220deSGabor Marton     //                 char *restrict node, socklen_t nodelen,
26543ff220deSGabor Marton     //                 char *restrict service,
26553ff220deSGabor Marton     //                 socklen_t servicelen, int flags);
26563ff220deSGabor Marton     //
26573ff220deSGabor Marton     // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr
26583ff220deSGabor Marton     // parameter is never handled as a transparent union in netdb.h
26593ff220deSGabor Marton     addToFunctionSummaryMap(
26603ff220deSGabor Marton         "getnameinfo",
266111d2e63aSGabor Marton         Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy,
2662a787a4edSGabor Marton                            CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy,
2663a787a4edSGabor Marton                            Socklen_tTy, IntTy},
266411d2e63aSGabor Marton                   RetType{IntTy}),
266511d2e63aSGabor Marton         Summary(NoEvalCall)
26663ff220deSGabor Marton             .ArgConstraint(
26673ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
26683ff220deSGabor Marton             .ArgConstraint(
2669a787a4edSGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax)))
26703ff220deSGabor Marton             .ArgConstraint(
26713ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3)))
26723ff220deSGabor Marton             .ArgConstraint(
2673a787a4edSGabor Marton                 ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax)))
26743ff220deSGabor Marton             .ArgConstraint(
26753ff220deSGabor Marton                 BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
26763ff220deSGabor Marton             .ArgConstraint(
2677a787a4edSGabor Marton                 ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax))));
2678f0b9dbcfSGabor Marton 
2679f0b9dbcfSGabor Marton     Optional<QualType> StructUtimbufTy = lookupTy("utimbuf");
2680f0b9dbcfSGabor Marton     Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy);
2681f0b9dbcfSGabor Marton 
2682f0b9dbcfSGabor Marton     // int utime(const char *filename, struct utimbuf *buf);
2683f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
268411d2e63aSGabor Marton         "utime",
268511d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}),
2686febe7503SGabor Marton         Summary(NoEvalCall)
2687957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2688957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2689febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2690f0b9dbcfSGabor Marton 
2691f0b9dbcfSGabor Marton     Optional<QualType> StructTimespecTy = lookupTy("timespec");
2692f0b9dbcfSGabor Marton     Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy);
2693f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTimespecPtrTy =
2694f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTimespecTy));
2695f0b9dbcfSGabor Marton 
2696f0b9dbcfSGabor Marton     // int futimens(int fd, const struct timespec times[2]);
2697f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
269811d2e63aSGabor Marton         "futimens",
269911d2e63aSGabor Marton         Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}),
270011d2e63aSGabor Marton         Summary(NoEvalCall)
2701957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2702957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
270311d2e63aSGabor Marton             .ArgConstraint(
270411d2e63aSGabor Marton                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2705f0b9dbcfSGabor Marton 
2706f0b9dbcfSGabor Marton     // int utimensat(int dirfd, const char *pathname,
2707f0b9dbcfSGabor Marton     //               const struct timespec times[2], int flags);
2708febe7503SGabor Marton     addToFunctionSummaryMap("utimensat",
2709febe7503SGabor Marton                             Signature(ArgTypes{IntTy, ConstCharPtrTy,
2710febe7503SGabor Marton                                                ConstStructTimespecPtrTy, IntTy},
271111d2e63aSGabor Marton                                       RetType{IntTy}),
2712febe7503SGabor Marton                             Summary(NoEvalCall)
2713957014daSBalázs Kéri                                 .Case(ReturnsZero, ErrnoMustNotBeChecked)
2714957014daSBalázs Kéri                                 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2715febe7503SGabor Marton                                 .ArgConstraint(NotNull(ArgNo(1))));
2716f0b9dbcfSGabor Marton 
2717f0b9dbcfSGabor Marton     Optional<QualType> StructTimevalTy = lookupTy("timeval");
2718f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTimevalPtrTy =
2719f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTimevalTy));
2720f0b9dbcfSGabor Marton 
2721f0b9dbcfSGabor Marton     // int utimes(const char *filename, const struct timeval times[2]);
2722f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
272311d2e63aSGabor Marton         "utimes",
272411d2e63aSGabor Marton         Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
272511d2e63aSGabor Marton                   RetType{IntTy}),
2726febe7503SGabor Marton         Summary(NoEvalCall)
2727957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2728957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2729febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2730f0b9dbcfSGabor Marton 
2731f0b9dbcfSGabor Marton     // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
2732f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2733f0b9dbcfSGabor Marton         "nanosleep",
273411d2e63aSGabor Marton         Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
273511d2e63aSGabor Marton                   RetType{IntTy}),
2736febe7503SGabor Marton         Summary(NoEvalCall)
2737957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2738957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2739febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(0))));
2740f0b9dbcfSGabor Marton 
2741f0b9dbcfSGabor Marton     Optional<QualType> Time_tTy = lookupTy("time_t");
2742f0b9dbcfSGabor Marton     Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy));
2743f0b9dbcfSGabor Marton     Optional<QualType> ConstTime_tPtrRestrictTy =
2744f0b9dbcfSGabor Marton         getRestrictTy(ConstTime_tPtrTy);
2745f0b9dbcfSGabor Marton 
2746f0b9dbcfSGabor Marton     Optional<QualType> StructTmTy = lookupTy("tm");
2747f0b9dbcfSGabor Marton     Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy);
2748f0b9dbcfSGabor Marton     Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy);
2749f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTmPtrTy =
2750f0b9dbcfSGabor Marton         getPointerTy(getConstTy(StructTmTy));
2751f0b9dbcfSGabor Marton     Optional<QualType> ConstStructTmPtrRestrictTy =
2752f0b9dbcfSGabor Marton         getRestrictTy(ConstStructTmPtrTy);
2753f0b9dbcfSGabor Marton 
2754f0b9dbcfSGabor Marton     // struct tm * localtime(const time_t *tp);
2755f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2756f0b9dbcfSGabor Marton         "localtime",
275711d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
275811d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2759f0b9dbcfSGabor Marton 
2760f0b9dbcfSGabor Marton     // struct tm *localtime_r(const time_t *restrict timer,
2761f0b9dbcfSGabor Marton     //                        struct tm *restrict result);
2762f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2763f0b9dbcfSGabor Marton         "localtime_r",
276411d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
276511d2e63aSGabor Marton                   RetType{StructTmPtrTy}),
276611d2e63aSGabor Marton         Summary(NoEvalCall)
2767f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2768f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2769f0b9dbcfSGabor Marton 
2770f0b9dbcfSGabor Marton     // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
2771f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2772f0b9dbcfSGabor Marton         "asctime_r",
277311d2e63aSGabor Marton         Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
277411d2e63aSGabor Marton                   RetType{CharPtrTy}),
277511d2e63aSGabor Marton         Summary(NoEvalCall)
2776f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2777f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2778f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2779f0b9dbcfSGabor Marton                                       /*MinBufSize=*/BVF.getValue(26, IntTy))));
2780f0b9dbcfSGabor Marton 
2781f0b9dbcfSGabor Marton     // char *ctime_r(const time_t *timep, char *buf);
278211d2e63aSGabor Marton     addToFunctionSummaryMap(
278311d2e63aSGabor Marton         "ctime_r",
278411d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}),
278511d2e63aSGabor Marton         Summary(NoEvalCall)
2786f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2787f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1)))
2788f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(
2789f0b9dbcfSGabor Marton                 /*Buffer=*/ArgNo(1),
2790f0b9dbcfSGabor Marton                 /*MinBufSize=*/BVF.getValue(26, IntTy))));
2791f0b9dbcfSGabor Marton 
2792f0b9dbcfSGabor Marton     // struct tm *gmtime_r(const time_t *restrict timer,
2793f0b9dbcfSGabor Marton     //                     struct tm *restrict result);
2794f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2795f0b9dbcfSGabor Marton         "gmtime_r",
279611d2e63aSGabor Marton         Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
279711d2e63aSGabor Marton                   RetType{StructTmPtrTy}),
279811d2e63aSGabor Marton         Summary(NoEvalCall)
2799f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2800f0b9dbcfSGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2801f0b9dbcfSGabor Marton 
2802f0b9dbcfSGabor Marton     // struct tm * gmtime(const time_t *tp);
2803f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
280411d2e63aSGabor Marton         "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
280511d2e63aSGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2806f0b9dbcfSGabor Marton 
2807f0b9dbcfSGabor Marton     Optional<QualType> Clockid_tTy = lookupTy("clockid_t");
2808f0b9dbcfSGabor Marton 
2809f0b9dbcfSGabor Marton     // int clock_gettime(clockid_t clock_id, struct timespec *tp);
281011d2e63aSGabor Marton     addToFunctionSummaryMap(
281111d2e63aSGabor Marton         "clock_gettime",
281211d2e63aSGabor Marton         Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}),
2813febe7503SGabor Marton         Summary(NoEvalCall)
2814957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2815957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2816febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2817f0b9dbcfSGabor Marton 
2818f0b9dbcfSGabor Marton     Optional<QualType> StructItimervalTy = lookupTy("itimerval");
2819f0b9dbcfSGabor Marton     Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy);
2820f0b9dbcfSGabor Marton 
2821f0b9dbcfSGabor Marton     // int getitimer(int which, struct itimerval *curr_value);
282211d2e63aSGabor Marton     addToFunctionSummaryMap(
282311d2e63aSGabor Marton         "getitimer",
282411d2e63aSGabor Marton         Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}),
2825febe7503SGabor Marton         Summary(NoEvalCall)
2826957014daSBalázs Kéri             .Case(ReturnsZero, ErrnoMustNotBeChecked)
2827957014daSBalázs Kéri             .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
2828febe7503SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2829d0128058SGabor Marton 
2830d0128058SGabor Marton     Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
2831d0128058SGabor Marton     Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy);
2832d0128058SGabor Marton     Optional<QualType> Pthread_tTy = lookupTy("pthread_t");
2833d0128058SGabor Marton     Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy);
2834d0128058SGabor Marton     Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy);
2835d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t");
2836d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy);
2837d0128058SGabor Marton     Optional<QualType> Pthread_mutex_tPtrRestrictTy =
2838d0128058SGabor Marton         getRestrictTy(Pthread_mutex_tPtrTy);
2839d0128058SGabor Marton     Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t");
2840d0128058SGabor Marton     Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy);
2841d0128058SGabor Marton     Optional<QualType> ConstPthread_attr_tPtrTy =
2842d0128058SGabor Marton         getPointerTy(getConstTy(Pthread_attr_tTy));
2843d0128058SGabor Marton     Optional<QualType> ConstPthread_attr_tPtrRestrictTy =
2844d0128058SGabor Marton         getRestrictTy(ConstPthread_attr_tPtrTy);
2845d0128058SGabor Marton     Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t");
2846d0128058SGabor Marton     Optional<QualType> ConstPthread_mutexattr_tPtrTy =
2847d0128058SGabor Marton         getPointerTy(getConstTy(Pthread_mutexattr_tTy));
2848d0128058SGabor Marton     Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy =
2849d0128058SGabor Marton         getRestrictTy(ConstPthread_mutexattr_tPtrTy);
2850d0128058SGabor Marton 
2851d0128058SGabor Marton     QualType PthreadStartRoutineTy = getPointerTy(
2852d0128058SGabor Marton         ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy,
2853d0128058SGabor Marton                              FunctionProtoType::ExtProtoInfo()));
2854d0128058SGabor Marton 
2855d0128058SGabor Marton     // int pthread_cond_signal(pthread_cond_t *cond);
2856d0128058SGabor Marton     // int pthread_cond_broadcast(pthread_cond_t *cond);
2857d0128058SGabor Marton     addToFunctionSummaryMap(
2858d0128058SGabor Marton         {"pthread_cond_signal", "pthread_cond_broadcast"},
2859d0128058SGabor Marton         Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}),
2860d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2861d0128058SGabor Marton 
2862d0128058SGabor Marton     // int pthread_create(pthread_t *restrict thread,
2863d0128058SGabor Marton     //                    const pthread_attr_t *restrict attr,
2864d0128058SGabor Marton     //                    void *(*start_routine)(void*), void *restrict arg);
2865d0128058SGabor Marton     addToFunctionSummaryMap(
2866d0128058SGabor Marton         "pthread_create",
2867d0128058SGabor Marton         Signature(ArgTypes{Pthread_tPtrRestrictTy,
2868d0128058SGabor Marton                            ConstPthread_attr_tPtrRestrictTy,
2869d0128058SGabor Marton                            PthreadStartRoutineTy, VoidPtrRestrictTy},
2870d0128058SGabor Marton                   RetType{IntTy}),
2871d0128058SGabor Marton         Summary(NoEvalCall)
2872d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2873d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(2))));
2874d0128058SGabor Marton 
2875d0128058SGabor Marton     // int pthread_attr_destroy(pthread_attr_t *attr);
2876d0128058SGabor Marton     // int pthread_attr_init(pthread_attr_t *attr);
2877d0128058SGabor Marton     addToFunctionSummaryMap(
2878d0128058SGabor Marton         {"pthread_attr_destroy", "pthread_attr_init"},
2879d0128058SGabor Marton         Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}),
2880d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2881d0128058SGabor Marton 
2882d0128058SGabor Marton     // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
2883d0128058SGabor Marton     //                               size_t *restrict stacksize);
2884d0128058SGabor Marton     // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr,
2885d0128058SGabor Marton     //                               size_t *restrict guardsize);
2886d0128058SGabor Marton     addToFunctionSummaryMap(
2887d0128058SGabor Marton         {"pthread_attr_getstacksize", "pthread_attr_getguardsize"},
2888d0128058SGabor Marton         Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy},
2889d0128058SGabor Marton                   RetType{IntTy}),
2890d0128058SGabor Marton         Summary(NoEvalCall)
2891d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2892d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2893d0128058SGabor Marton 
2894d0128058SGabor Marton     // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
2895d0128058SGabor Marton     // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
2896d0128058SGabor Marton     addToFunctionSummaryMap(
2897d0128058SGabor Marton         {"pthread_attr_setstacksize", "pthread_attr_setguardsize"},
2898d0128058SGabor Marton         Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}),
2899d0128058SGabor Marton         Summary(NoEvalCall)
2900d0128058SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
2901d0128058SGabor Marton             .ArgConstraint(
2902d0128058SGabor Marton                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
2903d0128058SGabor Marton 
2904d0128058SGabor Marton     // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const
2905d0128058SGabor Marton     //                        pthread_mutexattr_t *restrict attr);
2906d0128058SGabor Marton     addToFunctionSummaryMap(
2907d0128058SGabor Marton         "pthread_mutex_init",
2908d0128058SGabor Marton         Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy,
2909d0128058SGabor Marton                            ConstPthread_mutexattr_tPtrRestrictTy},
2910d0128058SGabor Marton                   RetType{IntTy}),
2911d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2912d0128058SGabor Marton 
2913d0128058SGabor Marton     // int pthread_mutex_destroy(pthread_mutex_t *mutex);
2914d0128058SGabor Marton     // int pthread_mutex_lock(pthread_mutex_t *mutex);
2915d0128058SGabor Marton     // int pthread_mutex_trylock(pthread_mutex_t *mutex);
2916d0128058SGabor Marton     // int pthread_mutex_unlock(pthread_mutex_t *mutex);
2917d0128058SGabor Marton     addToFunctionSummaryMap(
2918d0128058SGabor Marton         {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock",
2919d0128058SGabor Marton          "pthread_mutex_unlock"},
2920d0128058SGabor Marton         Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}),
2921d0128058SGabor Marton         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2922db4d5f70SGabor Marton   }
2923db4d5f70SGabor Marton 
29241525232eSGabor Marton   // Functions for testing.
29251525232eSGabor Marton   if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
292662e747f6SGabor Marton     addToFunctionSummaryMap(
2927a7cb951fSGabor Marton         "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2928a7cb951fSGabor Marton         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2929a7cb951fSGabor Marton 
2930a7cb951fSGabor Marton     // Test range values.
2931a7cb951fSGabor Marton     addToFunctionSummaryMap(
2932a7cb951fSGabor Marton         "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2933a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2934a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2935a7cb951fSGabor Marton     addToFunctionSummaryMap(
2936a7cb951fSGabor Marton         "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2937a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2938a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2))));
2939a7cb951fSGabor Marton     addToFunctionSummaryMap("__range_1_2__4_5",
2940a7cb951fSGabor Marton                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
2941a7cb951fSGabor Marton                             Summary(EvalCallAsPure)
2942a7cb951fSGabor Marton                                 .ArgConstraint(ArgumentCondition(
2943a7cb951fSGabor Marton                                     0U, WithinRange, Range({1, 2}, {4, 5}))));
2944a7cb951fSGabor Marton 
2945a7cb951fSGabor Marton     // Test range kind.
2946a7cb951fSGabor Marton     addToFunctionSummaryMap(
2947a7cb951fSGabor Marton         "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2948a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2949a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2950a7cb951fSGabor Marton     addToFunctionSummaryMap(
2951a7cb951fSGabor Marton         "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2952a7cb951fSGabor Marton         Summary(EvalCallAsPure)
2953a7cb951fSGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))));
2954a7cb951fSGabor Marton 
2955a7cb951fSGabor Marton     addToFunctionSummaryMap(
295662e747f6SGabor Marton         "__two_constrained_args",
295711d2e63aSGabor Marton         Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
295811d2e63aSGabor Marton         Summary(EvalCallAsPure)
295962e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))
296062e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1))));
296162e747f6SGabor Marton     addToFunctionSummaryMap(
296211d2e63aSGabor Marton         "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}),
296311d2e63aSGabor Marton         Summary(EvalCallAsPure)
296462e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))
296562e747f6SGabor Marton             .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2))));
296662e747f6SGabor Marton     addToFunctionSummaryMap(
296762e747f6SGabor Marton         "__defaultparam",
296811d2e63aSGabor Marton         Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}),
296911d2e63aSGabor Marton         Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
297011d2e63aSGabor Marton     addToFunctionSummaryMap(
297111d2e63aSGabor Marton         "__variadic",
297211d2e63aSGabor Marton         Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}),
297311d2e63aSGabor Marton         Summary(EvalCallAsPure)
29748f961399SGabor Marton             .ArgConstraint(NotNull(ArgNo(0)))
297562e747f6SGabor Marton             .ArgConstraint(NotNull(ArgNo(1))));
2976bd03ef19SGabor Marton     addToFunctionSummaryMap(
2977bd03ef19SGabor Marton         "__buf_size_arg_constraint",
297811d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}),
297911d2e63aSGabor Marton         Summary(EvalCallAsPure)
2980bd03ef19SGabor Marton             .ArgConstraint(
2981bd03ef19SGabor Marton                 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))));
298241928c97SGabor Marton     addToFunctionSummaryMap(
298341928c97SGabor Marton         "__buf_size_arg_constraint_mul",
298411d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}),
298511d2e63aSGabor Marton         Summary(EvalCallAsPure)
298641928c97SGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
298741928c97SGabor Marton                                       /*BufSizeMultiplier=*/ArgNo(2))));
2988fe0972d3SGabor Marton     addToFunctionSummaryMap(
2989f0b9dbcfSGabor Marton         "__buf_size_arg_constraint_concrete",
299011d2e63aSGabor Marton         Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}),
299111d2e63aSGabor Marton         Summary(EvalCallAsPure)
2992f0b9dbcfSGabor Marton             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0),
2993f0b9dbcfSGabor Marton                                       /*BufSize=*/BVF.getValue(10, IntTy))));
2994f0b9dbcfSGabor Marton     addToFunctionSummaryMap(
2995fe0972d3SGabor Marton         {"__test_restrict_param_0", "__test_restrict_param_1",
2996fe0972d3SGabor Marton          "__test_restrict_param_2"},
2997fe0972d3SGabor Marton         Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
2998fe0972d3SGabor Marton         Summary(EvalCallAsPure));
29991525232eSGabor Marton   }
3000c7635040SValeriy Savchenko 
3001c7635040SValeriy Savchenko   SummariesInitialized = true;
3002bba497fbSArtem Dergachev }
3003bba497fbSArtem Dergachev 
registerStdCLibraryFunctionsChecker(CheckerManager & mgr)3004bba497fbSArtem Dergachev void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
3005ff4492c8SGabor Marton   auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
3006edde4efcSBalazs Benics   const AnalyzerOptions &Opts = mgr.getAnalyzerOptions();
3007ff4492c8SGabor Marton   Checker->DisplayLoadedSummaries =
3008edde4efcSBalazs Benics       Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries");
3009edde4efcSBalazs Benics   Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX");
3010edde4efcSBalazs Benics   Checker->ShouldAssumeControlledEnvironment =
3011edde4efcSBalazs Benics       Opts.ShouldAssumeControlledEnvironment;
3012bba497fbSArtem Dergachev }
3013058a7a45SKristof Umann 
shouldRegisterStdCLibraryFunctionsChecker(const CheckerManager & mgr)301425bbe234SZurab Tsinadze bool ento::shouldRegisterStdCLibraryFunctionsChecker(
301525bbe234SZurab Tsinadze     const CheckerManager &mgr) {
3016058a7a45SKristof Umann   return true;
3017058a7a45SKristof Umann }
301894061df6SGabor Marton 
301994061df6SGabor Marton #define REGISTER_CHECKER(name)                                                 \
302094061df6SGabor Marton   void ento::register##name(CheckerManager &mgr) {                             \
302194061df6SGabor Marton     StdLibraryFunctionsChecker *checker =                                      \
302294061df6SGabor Marton         mgr.getChecker<StdLibraryFunctionsChecker>();                          \
302394061df6SGabor Marton     checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
302494061df6SGabor Marton     checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
302594061df6SGabor Marton         mgr.getCurrentCheckerName();                                           \
302694061df6SGabor Marton   }                                                                            \
302794061df6SGabor Marton                                                                                \
3028bda3dd0dSKirstóf Umann   bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
302994061df6SGabor Marton 
303094061df6SGabor Marton REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
30311525232eSGabor Marton REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)
3032