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