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