Coverage Report

Created: 2022-01-25 06:29

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
Line
Count
Source (jump to first uncovered line)
1
//=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This checker improves modeling of a few simple library functions.
10
//
11
// This checker provides a specification format - `Summary' - and
12
// contains descriptions of some library functions in this format. Each
13
// specification contains a list of branches for splitting the program state
14
// upon call, and range constraints on argument and return-value symbols that
15
// are satisfied on each branch. This spec can be expanded to include more
16
// items, like external effects of the function.
17
//
18
// The main difference between this approach and the body farms technique is
19
// in more explicit control over how many branches are produced. For example,
20
// consider standard C function `ispunct(int x)', which returns a non-zero value
21
// iff `x' is a punctuation character, that is, when `x' is in range
22
//   ['!', '/']   [':', '@']  U  ['[', '\`']  U  ['{', '~'].
23
// `Summary' provides only two branches for this function. However,
24
// any attempt to describe this range with if-statements in the body farm
25
// would result in many more branches. Because each branch needs to be analyzed
26
// independently, this significantly reduces performance. Additionally,
27
// once we consider a branch on which `x' is in range, say, ['!', '/'],
28
// we assume that such branch is an important separate path through the program,
29
// which may lead to false positives because considering this particular path
30
// was not consciously intended, and therefore it might have been unreachable.
31
//
32
// This checker uses eval::Call for modeling pure functions (functions without
33
// side effets), for which their `Summary' is a precise model. This avoids
34
// unnecessary invalidation passes. Conflicts with other checkers are unlikely
35
// because if the function has no other effects, other checkers would probably
36
// never want to improve upon the modeling done by this checker.
37
//
38
// Non-pure functions, for which only partial improvement over the default
39
// behavior is expected, are modeled via check::PostCall, non-intrusively.
40
//
41
// The following standard C functions are currently supported:
42
//
43
//   fgetc      getline   isdigit   isupper     toascii
44
//   fread      isalnum   isgraph   isxdigit
45
//   fwrite     isalpha   islower   read
46
//   getc       isascii   isprint   write
47
//   getchar    isblank   ispunct   toupper
48
//   getdelim   iscntrl   isspace   tolower
49
//
50
//===----------------------------------------------------------------------===//
51
52
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
53
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
54
#include "clang/StaticAnalyzer/Core/Checker.h"
55
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
56
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
57
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
58
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
59
#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
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
5.53k
    ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {}
114
5.94k
    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
0
    virtual ValueConstraintPtr negate() const {
121
0
      llvm_unreachable("Not implemented");
122
0
    };
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
827
    bool checkValidity(const FunctionDecl *FD) const {
128
827
      const bool ValidArg = ArgN == Ret || 
ArgN < FD->getNumParams()487
;
129
827
      assert(ValidArg && "Arg out of range!");
130
827
      if (!ValidArg)
131
0
        return false;
132
      // Subclasses may further refine the validation.
133
827
      return checkSpecificValidity(FD);
134
827
    }
135
4.23k
    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
30
    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.
147
    virtual std::string describe(ProgramStateRef State,
148
0
                                 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
0
      llvm_unreachable("Not implemented");
153
0
    }
154
155
  protected:
156
    ArgNo ArgN; // Argument to which we apply the constraint.
157
158
    /// Do polymorphic validation check on the constraint.
159
41
    virtual bool checkSpecificValidity(const FunctionDecl *FD) const {
160
41
      return true;
161
41
    }
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
22
    StringRef getName() const override { return "Range"; }
182
    RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges)
183
4.22k
        : ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {}
184
185
    std::string describe(ProgramStateRef State,
186
                         const Summary &Summary) const override;
187
188
1.04k
    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
1.04k
                          CheckerContext &C) const override {
202
1.04k
      switch (Kind) {
203
407
      case OutOfRange:
204
407
        return applyAsOutOfRange(State, Call, Summary);
205
639
      case WithinRange:
206
639
        return applyAsWithinRange(State, Call, Summary);
207
1.04k
      }
208
0
      llvm_unreachable("Unknown range kind!");
209
0
    }
210
211
57
    ValueConstraintPtr negate() const override {
212
57
      RangeConstraint Tmp(*this);
213
57
      switch (Kind) {
214
5
      case OutOfRange:
215
5
        Tmp.Kind = WithinRange;
216
5
        break;
217
52
      case WithinRange:
218
52
        Tmp.Kind = OutOfRange;
219
52
        break;
220
57
      }
221
57
      return std::make_shared<RangeConstraint>(Tmp);
222
57
    }
223
224
563
    bool checkSpecificValidity(const FunctionDecl *FD) const override {
225
563
      const bool ValidArg =
226
563
          getArgType(FD, ArgN)->isIntegralType(FD->getASTContext());
227
563
      assert(ValidArg &&
228
563
             "This constraint should be applied on an integral type");
229
0
      return ValidArg;
230
563
    }
231
  };
232
233
  class ComparisonConstraint : public ValueConstraint {
234
    BinaryOperator::Opcode Opcode;
235
    ArgNo OtherArgN;
236
237
  public:
238
0
    virtual StringRef getName() const override { return "Comparison"; };
239
    ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode,
240
                         ArgNo OtherArgN)
241
148
        : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {}
242
46
    ArgNo getOtherArgNo() const { return OtherArgN; }
243
46
    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:
255
    std::string describe(ProgramStateRef State,
256
                         const Summary &Summary) const override;
257
8
    StringRef getName() const override { return "NonNull"; }
258
    ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
259
                          const Summary &Summary,
260
120
                          CheckerContext &C) const override {
261
120
      SVal V = getArgSVal(Call, getArgNo());
262
120
      if (V.isUndef())
263
0
        return State;
264
265
120
      DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>();
266
120
      if (!L.getAs<Loc>())
267
0
        return State;
268
269
120
      return State->assume(L, CannotBeNull);
270
120
    }
271
272
108
    ValueConstraintPtr negate() const override {
273
108
      NotNullConstraint Tmp(*this);
274
108
      Tmp.CannotBeNull = !this->CannotBeNull;
275
108
      return std::make_shared<NotNullConstraint>(Tmp);
276
108
    }
277
278
175
    bool checkSpecificValidity(const FunctionDecl *FD) const override {
279
175
      const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
280
175
      assert(ValidArg &&
281
175
             "This constraint should be applied only on a pointer type");
282
0
      return ValidArg;
283
175
    }
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
13
    StringRef getName() const override { return "BufferSize"; }
310
    BufferSizeConstraint(ArgNo Buffer, llvm::APSInt BufMinSize)
311
21
        : ValueConstraint(Buffer), ConcreteSize(BufMinSize) {}
312
    BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize)
313
84
        : ValueConstraint(Buffer), SizeArgN(BufSize) {}
314
    BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier)
315
        : ValueConstraint(Buffer), SizeArgN(BufSize),
316
60
          SizeMultiplierArgN(BufSizeMultiplier) {}
317
318
13
    std::vector<ArgNo> getArgsToTrack() const override {
319
13
      std::vector<ArgNo> Result{ArgN};
320
13
      if (SizeArgN)
321
10
        Result.push_back(*SizeArgN);
322
13
      if (SizeMultiplierArgN)
323
6
        Result.push_back(*SizeMultiplierArgN);
324
13
      return Result;
325
13
    }
326
327
    std::string describe(ProgramStateRef State,
328
                         const Summary &Summary) const override;
329
330
    ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
331
                          const Summary &Summary,
332
80
                          CheckerContext &C) const override {
333
80
      SValBuilder &SvalBuilder = C.getSValBuilder();
334
      // The buffer argument.
335
80
      SVal BufV = getArgSVal(Call, getArgNo());
336
337
      // Get the size constraint.
338
80
      const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() {
339
80
        if (ConcreteSize) {
340
6
          return SVal(SvalBuilder.makeIntVal(*ConcreteSize));
341
6
        }
342
74
        assert(SizeArgN && "The constraint must be either a concrete value or "
343
74
                           "encoded in an argument.");
344
        // The size argument.
345
0
        SVal SizeV = getArgSVal(Call, *SizeArgN);
346
        // Multiply with another argument if given.
347
74
        if (SizeMultiplierArgN) {
348
58
          SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN);
349
58
          SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV,
350
58
                                        Summary.getArgType(*SizeArgN));
351
58
        }
352
74
        return SizeV;
353
80
      }();
354
355
      // The dynamic size of the buffer argument, got from the analyzer engine.
356
80
      SVal BufDynSize = getDynamicExtentWithOffset(State, BufV);
357
358
80
      SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize,
359
80
                                            SvalBuilder.getContext().BoolTy);
360
80
      if (auto F = Feasible.getAs<DefinedOrUnknownSVal>())
361
80
        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
0
      llvm_unreachable("Size argument or the dynamic size is Undefined");
370
0
    }
371
372
40
    ValueConstraintPtr negate() const override {
373
40
      BufferSizeConstraint Tmp(*this);
374
40
      Tmp.Op = BinaryOperator::negateComparisonOp(Op);
375
40
      return std::make_shared<BufferSizeConstraint>(Tmp);
376
40
    }
377
378
48
    bool checkSpecificValidity(const FunctionDecl *FD) const override {
379
48
      const bool ValidArg = getArgType(FD, ArgN)->isPointerType();
380
48
      assert(ValidArg &&
381
48
             "This constraint should be applied only on a pointer type");
382
0
      return ValidArg;
383
48
    }
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
935
  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
2.21k
    Signature(ArgTypes ArgTys, RetType RetTy) {
412
3.94k
      for (Optional<QualType> Arg : ArgTys) {
413
3.94k
        if (!Arg) {
414
540
          Invalid = true;
415
540
          return;
416
3.40k
        } else {
417
3.40k
          assertArgTypeSuitableForSignature(*Arg);
418
3.40k
          this->ArgTys.push_back(*Arg);
419
3.40k
        }
420
3.94k
      }
421
1.67k
      if (!RetTy) {
422
162
        Invalid = true;
423
162
        return;
424
1.51k
      } else {
425
1.51k
        assertRetTypeSuitableForSignature(*RetTy);
426
1.51k
        this->RetTy = *RetTy;
427
1.51k
      }
428
1.67k
    }
429
430
2.63k
    bool isInvalid() const { return Invalid; }
431
    bool matches(const FunctionDecl *FD) const;
432
433
  private:
434
3.40k
    static void assertArgTypeSuitableForSignature(QualType T) {
435
3.40k
      assert((T.isNull() || !T->isVoidType()) &&
436
3.40k
             "We should have no void types in the spec");
437
0
      assert((T.isNull() || T.isCanonical()) &&
438
3.40k
             "We should only have canonical types in the spec");
439
3.40k
    }
440
1.51k
    static void assertRetTypeSuitableForSignature(QualType T) {
441
1.51k
      assert((T.isNull() || T.isCanonical()) &&
442
1.51k
             "We should only have canonical types in the spec");
443
1.51k
    }
444
  };
445
446
2.00k
  static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) {
447
2.00k
    assert(FD && "Function must be set");
448
2.00k
    QualType T = (ArgN == Ret)
449
2.00k
                     ? 
FD->getReturnType().getCanonicalType()799
450
2.00k
                     : 
FD->getParamDecl(ArgN)->getType().getCanonicalType()1.20k
;
451
2.00k
    return T;
452
2.00k
  }
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
2.03k
    Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {}
494
495
2.15k
    Summary &Case(ConstraintSet &&CS) {
496
2.15k
      CaseConstraints.push_back(std::move(CS));
497
2.15k
      return *this;
498
2.15k
    }
499
416
    Summary &Case(const ConstraintSet &CS) {
500
416
      CaseConstraints.push_back(CS);
501
416
      return *this;
502
416
    }
503
1.74k
    Summary &ArgConstraint(ValueConstraintPtr VC) {
504
1.74k
      assert(VC->getArgNo() != Ret &&
505
1.74k
             "Arg constraint should not refer to the return value");
506
0
      ArgConstraints.push_back(VC);
507
1.74k
      return *this;
508
1.74k
    }
509
510
426
    InvalidationKind getInvalidationKd() const { return InvalidationKd; }
511
412
    const Cases &getCaseConstraints() const { return CaseConstraints; }
512
467
    const ConstraintSet &getArgConstraints() const { return ArgConstraints; }
513
514
1.21k
    QualType getArgType(ArgNo ArgN) const {
515
1.21k
      return StdLibraryFunctionsChecker::getArgType(FD, ArgN);
516
1.21k
    }
517
518
    // Returns true if the summary should be applied to the given function.
519
    // And if yes then store the function declaration.
520
309
    bool matchesAndSet(const Signature &Sign, const FunctionDecl *FD) {
521
309
      bool Result = Sign.matches(FD) && 
validateByConstraints(FD)300
;
522
309
      if (Result) {
523
300
        assert(!this->FD && "FD must not be set more than once");
524
0
        this->FD = FD;
525
300
      }
526
0
      return Result;
527
309
    }
528
529
  private:
530
    // Once we know the exact type of the function then do validation check on
531
    // all the given constraints.
532
300
    bool validateByConstraints(const FunctionDecl *FD) const {
533
300
      for (const ConstraintSet &Case : CaseConstraints)
534
328
        for (const ValueConstraintPtr &Constraint : Case)
535
519
          if (!Constraint->checkValidity(FD))
536
0
            return false;
537
300
      for (const ValueConstraintPtr &Constraint : ArgConstraints)
538
308
        if (!Constraint->checkValidity(FD))
539
0
          return false;
540
300
      return true;
541
300
    }
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
1.47k
  static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) {
553
1.47k
    return ArgN == Ret ? 
Call.getReturnValue()510
:
Call.getArgSVal(ArgN)960
;
554
1.47k
  }
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
43
                 CheckerContext &C) const {
584
43
    if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker])
585
0
      return;
586
43
    std::string Msg =
587
43
        (Twine("Function argument constraint is not satisfied, constraint: ") +
588
43
         VC->getName().data())
589
43
            .str();
590
43
    if (!BT_InvalidArg)
591
5
      BT_InvalidArg = std::make_unique<BugType>(
592
5
          CheckNames[CK_StdCLibraryFunctionArgsChecker],
593
5
          "Unsatisfied argument constraints", categories::LogicError);
594
43
    auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N);
595
596
43
    for (ArgNo ArgN : VC->getArgsToTrack())
597
59
      bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R);
598
599
    // Highlight the range of the argument that was violated.
600
43
    R->addRange(Call.getArgSourceRange(VC->getArgNo()));
601
602
    // Describe the argument constraint in a note.
603
43
    R->addNote(VC->describe(C.getState(), Summary), R->getLocation(),
604
43
               Call.getArgSourceRange(VC->getArgNo()));
605
606
43
    C.emitReport(std::move(R));
607
43
  }
608
};
609
610
const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret =
611
    std::numeric_limits<ArgNo>::max();
612
613
} // end of anonymous namespace
614
615
22
static BasicValueFactory &getBVF(ProgramStateRef State) {
616
22
  ProgramStateManager &Mgr = State->getStateManager();
617
22
  SValBuilder &SVB = Mgr.getSValBuilder();
618
22
  return SVB.getBasicValueFactory();
619
22
}
620
621
std::string StdLibraryFunctionsChecker::NotNullConstraint::describe(
622
8
    ProgramStateRef State, const Summary &Summary) const {
623
8
  SmallString<48> Result;
624
8
  Result += "The ";
625
8
  Result += getArgDesc(ArgN);
626
8
  Result += " should not be NULL";
627
8
  return Result.c_str();
628
8
}
629
630
std::string StdLibraryFunctionsChecker::RangeConstraint::describe(
631
22
    ProgramStateRef State, const Summary &Summary) const {
632
633
22
  BasicValueFactory &BVF = getBVF(State);
634
635
22
  QualType T = Summary.getArgType(getArgNo());
636
22
  SmallString<48> Result;
637
22
  Result += "The ";
638
22
  Result += getArgDesc(ArgN);
639
22
  Result += " should be ";
640
641
  // Range kind as a string.
642
22
  Kind == OutOfRange ? 
Result += "out of"1
:
Result += "within"21
;
643
644
  // Get the range values as a string.
645
22
  Result += " the range ";
646
22
  if (Ranges.size() > 1)
647
17
    Result += "[";
648
22
  unsigned I = Ranges.size();
649
39
  for (const std::pair<RangeInt, RangeInt> &R : Ranges) {
650
39
    Result += "[";
651
39
    const llvm::APSInt &Min = BVF.getValue(R.first, T);
652
39
    const llvm::APSInt &Max = BVF.getValue(R.second, T);
653
39
    Min.toString(Result);
654
39
    Result += ", ";
655
39
    Max.toString(Result);
656
39
    Result += "]";
657
39
    if (--I > 0)
658
17
      Result += ", ";
659
39
  }
660
22
  if (Ranges.size() > 1)
661
17
    Result += "]";
662
663
22
  return Result.c_str();
664
22
}
665
666
SmallString<8>
667
59
StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) {
668
59
  SmallString<8> Result;
669
59
  Result += std::to_string(ArgN + 1);
670
59
  Result += llvm::getOrdinalSuffix(ArgN + 1);
671
59
  Result += " arg";
672
59
  return Result;
673
59
}
674
675
std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe(
676
13
    ProgramStateRef State, const Summary &Summary) const {
677
13
  SmallString<96> Result;
678
13
  Result += "The size of the ";
679
13
  Result += getArgDesc(ArgN);
680
13
  Result += " should be equal to or less than the value of ";
681
13
  if (ConcreteSize) {
682
3
    ConcreteSize->toString(Result);
683
10
  } else if (SizeArgN) {
684
10
    Result += "the ";
685
10
    Result += getArgDesc(*SizeArgN);
686
10
    if (SizeMultiplierArgN) {
687
6
      Result += " times the ";
688
6
      Result += getArgDesc(*SizeMultiplierArgN);
689
6
    }
690
10
  }
691
13
  return Result.c_str();
692
13
}
693
694
ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange(
695
    ProgramStateRef State, const CallEvent &Call,
696
407
    const Summary &Summary) const {
697
407
  if (Ranges.empty())
698
0
    return State;
699
700
407
  ProgramStateManager &Mgr = State->getStateManager();
701
407
  SValBuilder &SVB = Mgr.getSValBuilder();
702
407
  BasicValueFactory &BVF = SVB.getBasicValueFactory();
703
407
  ConstraintManager &CM = Mgr.getConstraintManager();
704
407
  QualType T = Summary.getArgType(getArgNo());
705
407
  SVal V = getArgSVal(Call, getArgNo());
706
707
407
  if (auto N = V.getAs<NonLoc>()) {
708
407
    const IntRangeVector &R = getRanges();
709
407
    size_t E = R.size();
710
911
    for (size_t I = 0; I != E; 
++I504
) {
711
613
      const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
712
613
      const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
713
613
      assert(Min <= Max);
714
0
      State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
715
613
      if (!State)
716
109
        break;
717
613
    }
718
407
  }
719
720
407
  return State;
721
407
}
722
723
ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange(
724
    ProgramStateRef State, const CallEvent &Call,
725
639
    const Summary &Summary) const {
726
639
  if (Ranges.empty())
727
0
    return State;
728
729
639
  ProgramStateManager &Mgr = State->getStateManager();
730
639
  SValBuilder &SVB = Mgr.getSValBuilder();
731
639
  BasicValueFactory &BVF = SVB.getBasicValueFactory();
732
639
  ConstraintManager &CM = Mgr.getConstraintManager();
733
639
  QualType T = Summary.getArgType(getArgNo());
734
639
  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
639
  if (auto N = V.getAs<NonLoc>()) {
746
639
    const IntRangeVector &R = getRanges();
747
639
    size_t E = R.size();
748
749
639
    const llvm::APSInt &MinusInf = BVF.getMinValue(T);
750
639
    const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
751
752
639
    const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
753
639
    if (Left != PlusInf) {
754
617
      assert(MinusInf <= Left);
755
0
      State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
756
617
      if (!State)
757
70
        return nullptr;
758
617
    }
759
760
569
    const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
761
569
    if (Right != MinusInf) {
762
499
      assert(Right <= PlusInf);
763
0
      State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
764
499
      if (!State)
765
31
        return nullptr;
766
499
    }
767
768
813
    
for (size_t I = 1; 538
I != E;
++I275
) {
769
291
      const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
770
291
      const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
771
291
      if (Min <= Max) {
772
165
        State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
773
165
        if (!State)
774
16
          return nullptr;
775
165
      }
776
291
    }
777
538
  }
778
779
522
  return State;
780
639
}
781
782
ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply(
783
    ProgramStateRef State, const CallEvent &Call, const Summary &Summary,
784
46
    CheckerContext &C) const {
785
786
46
  ProgramStateManager &Mgr = State->getStateManager();
787
46
  SValBuilder &SVB = Mgr.getSValBuilder();
788
46
  QualType CondT = SVB.getConditionType();
789
46
  QualType T = Summary.getArgType(getArgNo());
790
46
  SVal V = getArgSVal(Call, getArgNo());
791
792
46
  BinaryOperator::Opcode Op = getOpcode();
793
46
  ArgNo OtherArg = getOtherArgNo();
794
46
  SVal OtherV = getArgSVal(Call, OtherArg);
795
46
  QualType OtherT = Summary.getArgType(OtherArg);
796
  // Note: we avoid integral promotion for comparison.
797
46
  OtherV = SVB.evalCast(OtherV, T, OtherT);
798
46
  if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
799
46
                       .getAs<DefinedOrUnknownSVal>())
800
46
    State = State->assume(*CompV, true);
801
46
  return State;
802
46
}
803
804
void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call,
805
1.00k
                                              CheckerContext &C) const {
806
1.00k
  Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
807
1.00k
  if (!FoundSummary)
808
542
    return;
809
810
467
  const Summary &Summary = *FoundSummary;
811
467
  ProgramStateRef State = C.getState();
812
813
467
  ProgramStateRef NewState = State;
814
467
  for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) {
815
152
    ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C);
816
152
    ProgramStateRef FailureSt =
817
152
        Constraint->negate()->apply(NewState, Call, Summary, C);
818
    // The argument constraint is not satisfied.
819
152
    if (FailureSt && 
!SuccessSt100
) {
820
43
      if (ExplodedNode *N = C.generateErrorNode(NewState))
821
43
        reportBug(Call, N, Constraint.get(), Summary, C);
822
43
      break;
823
109
    } 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
109
      assert(SuccessSt);
829
0
      NewState = SuccessSt;
830
109
    }
831
152
  }
832
467
  if (NewState && NewState != State)
833
37
    C.addTransition(NewState);
834
467
}
835
836
void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
837
942
                                               CheckerContext &C) const {
838
942
  Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
839
942
  if (!FoundSummary)
840
530
    return;
841
842
  // Now apply the constraints.
843
412
  const Summary &Summary = *FoundSummary;
844
412
  ProgramStateRef State = C.getState();
845
846
  // Apply case/branch specifications.
847
667
  for (const ConstraintSet &Case : Summary.getCaseConstraints()) {
848
667
    ProgramStateRef NewState = State;
849
988
    for (const ValueConstraintPtr &Constraint : Case) {
850
988
      NewState = Constraint->apply(NewState, Call, Summary, C);
851
988
      if (!NewState)
852
186
        break;
853
988
    }
854
855
667
    if (NewState && 
NewState != State481
)
856
474
      C.addTransition(NewState);
857
667
  }
858
412
}
859
860
bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
861
962
                                          CheckerContext &C) const {
862
962
  Optional<Summary> FoundSummary = findFunctionSummary(Call, C);
863
962
  if (!FoundSummary)
864
536
    return false;
865
866
426
  const Summary &Summary = *FoundSummary;
867
426
  switch (Summary.getInvalidationKd()) {
868
211
  case EvalCallAsPure: {
869
211
    ProgramStateRef State = C.getState();
870
211
    const LocationContext *LC = C.getLocationContext();
871
211
    const auto *CE = cast<CallExpr>(Call.getOriginExpr());
872
211
    SVal V = C.getSValBuilder().conjureSymbolVal(
873
211
        CE, LC, CE->getType().getCanonicalType(), C.blockCount());
874
211
    State = State->BindExpr(CE, LC, V);
875
211
    C.addTransition(State);
876
211
    return true;
877
0
  }
878
215
  case NoEvalCall:
879
    // Summary tells us to avoid performing eval::Call. The function is possibly
880
    // evaluated by another checker, or evaluated conservatively.
881
215
    return false;
882
426
  }
883
0
  llvm_unreachable("Unknown invalidation kind!");
884
0
}
885
886
bool StdLibraryFunctionsChecker::Signature::matches(
887
309
    const FunctionDecl *FD) const {
888
309
  assert(!isInvalid());
889
  // Check the number of arguments.
890
309
  if (FD->param_size() != ArgTys.size())
891
0
    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
927
  
auto RemoveRestrict = [&FD](QualType T) 309
{
901
927
    if (!FD->getASTContext().getLangOpts().C99)
902
67
      T.removeLocalRestrict();
903
927
    return T;
904
927
  };
905
906
  // Check the return type.
907
309
  if (!isIrrelevant(RetTy)) {
908
309
    QualType FDRetTy = RemoveRestrict(FD->getReturnType().getCanonicalType());
909
309
    if (RetTy != FDRetTy)
910
1
      return false;
911
309
  }
912
913
  // Check the argument types.
914
926
  
for (size_t I = 0, E = ArgTys.size(); 308
I != E;
++I618
) {
915
626
    QualType ArgTy = ArgTys[I];
916
626
    if (isIrrelevant(ArgTy))
917
8
      continue;
918
618
    QualType FDArgTy =
919
618
        RemoveRestrict(FD->getParamDecl(I)->getType().getCanonicalType());
920
618
    if (ArgTy != FDArgTy)
921
8
      return false;
922
618
  }
923
924
300
  return true;
925
308
}
926
927
Optional<StdLibraryFunctionsChecker::Summary>
928
StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
929
2.90k
                                                CheckerContext &C) const {
930
2.90k
  if (!FD)
931
0
    return None;
932
933
2.90k
  initFunctionSummaries(C);
934
935
2.90k
  auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl());
936
2.90k
  if (FSMI == FunctionSummaryMap.end())
937
1.60k
    return None;
938
1.30k
  return FSMI->second;
939
2.90k
}
940
941
Optional<StdLibraryFunctionsChecker::Summary>
942
StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call,
943
2.91k
                                                CheckerContext &C) const {
944
2.91k
  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
945
2.91k
  if (!FD)
946
6
    return None;
947
2.90k
  return findFunctionSummary(FD, C);
948
2.91k
}
949
950
void StdLibraryFunctionsChecker::initFunctionSummaries(
951
2.90k
    CheckerContext &C) const {
952
2.90k
  if (SummariesInitialized)
953
2.85k
    return;
954
955
53
  SValBuilder &SVB = C.getSValBuilder();
956
53
  BasicValueFactory &BVF = SVB.getBasicValueFactory();
957
53
  const ASTContext &ACtx = BVF.getContext();
958
959
  // Helper class to lookup a type by its name.
960
53
  class LookupType {
961
53
    const ASTContext &ACtx;
962
963
53
  public:
964
53
    LookupType(const ASTContext &ACtx) : ACtx(ACtx) {}
965
966
    // Find the type. If not found then the optional is not set.
967
267
    llvm::Optional<QualType> operator()(StringRef Name) {
968
267
      IdentifierInfo &II = ACtx.Idents.get(Name);
969
267
      auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
970
267
      if (LookupRes.empty())
971
211
        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
56
      for (Decl *D : LookupRes)
979
74
        if (auto *TD = dyn_cast<TypedefNameDecl>(D))
980
47
          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
9
      for (Decl *D : LookupRes)
987
9
        if (auto *TD = dyn_cast<TypeDecl>(D))
988
9
          return ACtx.getTypeDeclType(TD).getCanonicalType();
989
0
      return None;
990
9
    }
991
53
  } lookupTy(ACtx);
992
993
  // Below are auxiliary classes to handle optional types that we get as a
994
  // result of the lookup.
995
53
  class GetRestrictTy {
996
53
    const ASTContext &ACtx;
997
998
53
  public:
999
53
    GetRestrictTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1000
353
    QualType operator()(QualType Ty) {
1001
353
      return ACtx.getLangOpts().C99 ? 
ACtx.getRestrictType(Ty)259
:
Ty94
;
1002
353
    }
1003
130
    Optional<QualType> operator()(Optional<QualType> Ty) {
1004
130
      if (Ty)
1005
35
        return operator()(*Ty);
1006
95
      return None;
1007
130
    }
1008
53
  } getRestrictTy(ACtx);
1009
53
  class GetPointerTy {
1010
53
    const ASTContext &ACtx;
1011
1012
53
  public:
1013
53
    GetPointerTy(const ASTContext &ACtx) : ACtx(ACtx) {}
1014
589
    QualType operator()(QualType Ty) { return ACtx.getPointerType(Ty); }
1015
200
    Optional<QualType> operator()(Optional<QualType> Ty) {
1016
200
      if (Ty)
1017
45
        return operator()(*Ty);
1018
155
      return None;
1019
200
    }
1020
53
  } getPointerTy(ACtx);
1021
53
  class {
1022
53
  public:
1023
56
    Optional<QualType> operator()(Optional<QualType> Ty) {
1024
56
      return Ty ? 
Optional<QualType>(Ty->withConst())9
:
None47
;
1025
56
    }
1026
166
    QualType operator()(QualType Ty) { return Ty.withConst(); }
1027
53
  } getConstTy;
1028
53
  class GetMaxValue {
1029
53
    BasicValueFactory &BVF;
1030
1031
53
  public:
1032
53
    GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {}
1033
53
    Optional<RangeInt> operator()(QualType Ty) {
1034
10
      return BVF.getMaxValue(Ty).getLimitedValue();
1035
10
    }
1036
60
    Optional<RangeInt> operator()(Optional<QualType> Ty) {
1037
60
      if (Ty) {
1038
10
        return operator()(*Ty);
1039
10
      }
1040
50
      return None;
1041
60
    }
1042
53
  } 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
53
  const QualType VoidTy = ACtx.VoidTy;
1052
53
  const QualType CharTy = ACtx.CharTy;
1053
53
  const QualType WCharTy = ACtx.WCharTy;
1054
53
  const QualType IntTy = ACtx.IntTy;
1055
53
  const QualType UnsignedIntTy = ACtx.UnsignedIntTy;
1056
53
  const QualType LongTy = ACtx.LongTy;
1057
53
  const QualType SizeTy = ACtx.getSizeType();
1058
1059
53
  const QualType VoidPtrTy = getPointerTy(VoidTy); // void *
1060
53
  const QualType IntPtrTy = getPointerTy(IntTy);   // int *
1061
53
  const QualType UnsignedIntPtrTy =
1062
53
      getPointerTy(UnsignedIntTy); // unsigned int *
1063
53
  const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy);
1064
53
  const QualType ConstVoidPtrTy =
1065
53
      getPointerTy(getConstTy(VoidTy));            // const void *
1066
53
  const QualType CharPtrTy = getPointerTy(CharTy); // char *
1067
53
  const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy);
1068
53
  const QualType ConstCharPtrTy =
1069
53
      getPointerTy(getConstTy(CharTy)); // const char *
1070
53
  const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy);
1071
53
  const QualType Wchar_tPtrTy = getPointerTy(WCharTy); // wchar_t *
1072
53
  const QualType ConstWchar_tPtrTy =
1073
53
      getPointerTy(getConstTy(WCharTy)); // const wchar_t *
1074
53
  const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy);
1075
53
  const QualType SizePtrTy = getPointerTy(SizeTy);
1076
53
  const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy);
1077
1078
53
  const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
1079
53
  const RangeInt UnsignedIntMax =
1080
53
      BVF.getMaxValue(UnsignedIntTy).getLimitedValue();
1081
53
  const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
1082
53
  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
53
  const RangeInt UCharRangeMax =
1091
53
      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
53
  const auto EOFv = [&C]() -> RangeInt {
1096
53
    if (const llvm::Optional<int> OptInt =
1097
53
            tryExpandAsInteger("EOF", C.getPreprocessor()))
1098
16
      return *OptInt;
1099
37
    return -1;
1100
53
  }();
1101
1102
  // Auxiliary class to aid adding summaries to the summary map.
1103
53
  struct AddToFunctionSummaryMap {
1104
53
    const ASTContext &ACtx;
1105
53
    FunctionSummaryMapType &Map;
1106
53
    bool DisplayLoadedSummaries;
1107
53
    AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM,
1108
53
                            bool DisplayLoadedSummaries)
1109
53
        : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) {
1110
53
    }
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
2.33k
    bool operator()(StringRef Name, Signature Sign, Summary Sum) {
1118
2.33k
      if (Sign.isInvalid())
1119
776
        return false;
1120
1.55k
      IdentifierInfo &II = ACtx.Idents.get(Name);
1121
1.55k
      auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II);
1122
1.55k
      if (LookupRes.empty())
1123
1.24k
        return false;
1124
310
      
for (Decl *D : LookupRes)309
{
1125
310
        if (auto *FD = dyn_cast<FunctionDecl>(D)) {
1126
309
          if (Sum.matchesAndSet(Sign, FD)) {
1127
300
            auto Res = Map.insert({FD->getCanonicalDecl(), Sum});
1128
300
            assert(Res.second && "Function already has a summary set!");
1129
0
            (void)Res;
1130
300
            if (DisplayLoadedSummaries) {
1131
166
              llvm::errs() << "Loaded summary for: ";
1132
166
              FD->print(llvm::errs());
1133
166
              llvm::errs() << "\n";
1134
166
            }
1135
300
            return true;
1136
300
          }
1137
309
        }
1138
310
      }
1139
9
      return false;
1140
309
    }
1141
    // Add the same summary for different names with the Signature explicitly
1142
    // given.
1143
95
    void operator()(std::vector<StringRef> Names, Signature Sign, Summary Sum) {
1144
95
      for (StringRef Name : Names)
1145
211
        operator()(Name, Sign, Sum);
1146
95
    }
1147
53
  } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries);
1148
1149
  // Below are helpers functions to create the summaries.
1150
53
  auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind,
1151
2.43k
                              IntRangeVector Ranges) {
1152
2.43k
    return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges);
1153
2.43k
  };
1154
165
  auto BufferSize = [](auto... Args) {
1155
165
    return std::make_shared<BufferSizeConstraint>(Args...);
1156
165
  };
StdLibraryFunctionsChecker.cpp:auto (anonymous namespace)::StdLibraryFunctionsChecker::initFunctionSummaries(clang::ento::CheckerContext&) const::$_3::operator()<unsigned int, unsigned int, unsigned int>(unsigned int, unsigned int, unsigned int) const
Line
Count
Source
1154
60
  auto BufferSize = [](auto... Args) {
1155
60
    return std::make_shared<BufferSizeConstraint>(Args...);
1156
60
  };
StdLibraryFunctionsChecker.cpp:auto (anonymous namespace)::StdLibraryFunctionsChecker::initFunctionSummaries(clang::ento::CheckerContext&) const::$_3::operator()<unsigned int, unsigned int>(unsigned int, unsigned int) const
Line
Count
Source
1154
84
  auto BufferSize = [](auto... Args) {
1155
84
    return std::make_shared<BufferSizeConstraint>(Args...);
1156
84
  };
StdLibraryFunctionsChecker.cpp:auto (anonymous namespace)::StdLibraryFunctionsChecker::initFunctionSummaries(clang::ento::CheckerContext&) const::$_3::operator()<unsigned int, llvm::APSInt>(unsigned int, llvm::APSInt) const
Line
Count
Source
1154
21
  auto BufferSize = [](auto... Args) {
1155
21
    return std::make_shared<BufferSizeConstraint>(Args...);
1156
21
  };
1157
53
  struct {
1158
1.79k
    auto operator()(RangeKind Kind, IntRangeVector Ranges) {
1159
1.79k
      return std::make_shared<RangeConstraint>(Ret, Kind, Ranges);
1160
1.79k
    }
1161
148
    auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) {
1162
148
      return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN);
1163
148
    }
1164
53
  } ReturnValueCondition;
1165
53
  struct {
1166
1.14k
    auto operator()(RangeInt b, RangeInt e) {
1167
1.14k
      return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}};
1168
1.14k
    }
1169
150
    auto operator()(RangeInt b, Optional<RangeInt> e) {
1170
150
      if (e)
1171
35
        return IntRangeVector{std::pair<RangeInt, RangeInt>{b, *e}};
1172
115
      return IntRangeVector{};
1173
150
    }
1174
53
    auto operator()(std::pair<RangeInt, RangeInt> i0,
1175
60
                    std::pair<RangeInt, Optional<RangeInt>> i1) {
1176
60
      if (i1.second)
1177
15
        return IntRangeVector{i0, {i1.first, *(i1.second)}};
1178
45
      return IntRangeVector{i0};
1179
60
    }
1180
53
  } Range;
1181
1.49k
  auto SingleValue = [](RangeInt v) {
1182
1.49k
    return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}};
1183
1.49k
  };
1184
53
  auto LessThanOrEq = BO_LE;
1185
1.00k
  auto NotNull = [&](ArgNo ArgN) {
1186
1.00k
    return std::make_shared<NotNullConstraint>(ArgN);
1187
1.00k
  };
1188
1189
53
  Optional<QualType> FileTy = lookupTy("FILE");
1190
53
  Optional<QualType> FilePtrTy = getPointerTy(FileTy);
1191
53
  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
53
  addToFunctionSummaryMap(
1209
53
      "isalnum", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1210
53
      Summary(EvalCallAsPure)
1211
          // Boils down to isupper() or islower() or isdigit().
1212
53
          .Case({ArgumentCondition(0U, WithinRange,
1213
53
                                   {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}),
1214
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1215
          // The locale-specific range.
1216
          // No post-condition. We are completely unaware of
1217
          // locale-specific return values.
1218
53
          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1219
53
          .Case(
1220
53
              {ArgumentCondition(
1221
53
                   0U, OutOfRange,
1222
53
                   {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1223
53
               ReturnValueCondition(WithinRange, SingleValue(0))})
1224
53
          .ArgConstraint(ArgumentCondition(
1225
53
              0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1226
53
  addToFunctionSummaryMap(
1227
53
      "isalpha", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1228
53
      Summary(EvalCallAsPure)
1229
53
          .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}),
1230
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1231
          // The locale-specific range.
1232
53
          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1233
53
          .Case({ArgumentCondition(
1234
53
                     0U, OutOfRange,
1235
53
                     {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
1236
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1237
53
  addToFunctionSummaryMap(
1238
53
      "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1239
53
      Summary(EvalCallAsPure)
1240
53
          .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1241
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1242
53
          .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)),
1243
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1244
53
  addToFunctionSummaryMap(
1245
53
      "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1246
53
      Summary(EvalCallAsPure)
1247
53
          .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}),
1248
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1249
53
          .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}),
1250
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1251
53
  addToFunctionSummaryMap(
1252
53
      "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1253
53
      Summary(EvalCallAsPure)
1254
53
          .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}),
1255
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1256
53
          .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}),
1257
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1258
53
  addToFunctionSummaryMap(
1259
53
      "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1260
53
      Summary(EvalCallAsPure)
1261
53
          .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')),
1262
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1263
53
          .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')),
1264
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1265
53
  addToFunctionSummaryMap(
1266
53
      "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1267
53
      Summary(EvalCallAsPure)
1268
53
          .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)),
1269
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1270
53
          .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)),
1271
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1272
53
  addToFunctionSummaryMap(
1273
53
      "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1274
53
      Summary(EvalCallAsPure)
1275
          // Is certainly lowercase.
1276
53
          .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')),
1277
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1278
          // Is ascii but not lowercase.
1279
53
          .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
1280
53
                 ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
1281
53
                 ReturnValueCondition(WithinRange, SingleValue(0))})
1282
          // The locale-specific range.
1283
53
          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1284
          // Is not an unsigned char.
1285
53
          .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)),
1286
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1287
53
  addToFunctionSummaryMap(
1288
53
      "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1289
53
      Summary(EvalCallAsPure)
1290
53
          .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
1291
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1292
53
          .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
1293
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1294
53
  addToFunctionSummaryMap(
1295
53
      "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1296
53
      Summary(EvalCallAsPure)
1297
53
          .Case({ArgumentCondition(
1298
53
                     0U, WithinRange,
1299
53
                     {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1300
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1301
53
          .Case({ArgumentCondition(
1302
53
                     0U, OutOfRange,
1303
53
                     {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
1304
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1305
53
  addToFunctionSummaryMap(
1306
53
      "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1307
53
      Summary(EvalCallAsPure)
1308
          // Space, '\f', '\n', '\r', '\t', '\v'.
1309
53
          .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}),
1310
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1311
          // The locale-specific range.
1312
53
          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1313
53
          .Case({ArgumentCondition(0U, OutOfRange,
1314
53
                                   {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
1315
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1316
53
  addToFunctionSummaryMap(
1317
53
      "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1318
53
      Summary(EvalCallAsPure)
1319
          // Is certainly uppercase.
1320
53
          .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
1321
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1322
          // The locale-specific range.
1323
53
          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
1324
          // Other.
1325
53
          .Case({ArgumentCondition(0U, OutOfRange,
1326
53
                                   {{'A', 'Z'}, {128, UCharRangeMax}}),
1327
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1328
53
  addToFunctionSummaryMap(
1329
53
      "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1330
53
      Summary(EvalCallAsPure)
1331
53
          .Case({ArgumentCondition(0U, WithinRange,
1332
53
                                   {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1333
53
                 ReturnValueCondition(OutOfRange, SingleValue(0))})
1334
53
          .Case({ArgumentCondition(0U, OutOfRange,
1335
53
                                   {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
1336
53
                 ReturnValueCondition(WithinRange, SingleValue(0))}));
1337
53
  addToFunctionSummaryMap(
1338
53
      "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1339
53
      Summary(EvalCallAsPure)
1340
53
          .ArgConstraint(ArgumentCondition(
1341
53
              0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1342
53
  addToFunctionSummaryMap(
1343
53
      "tolower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1344
53
      Summary(EvalCallAsPure)
1345
53
          .ArgConstraint(ArgumentCondition(
1346
53
              0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1347
53
  addToFunctionSummaryMap(
1348
53
      "toascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1349
53
      Summary(EvalCallAsPure)
1350
53
          .ArgConstraint(ArgumentCondition(
1351
53
              0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
1352
1353
  // The getc() family of functions that returns either a char or an EOF.
1354
53
  addToFunctionSummaryMap(
1355
53
      {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1356
53
      Summary(NoEvalCall)
1357
53
          .Case({ReturnValueCondition(WithinRange,
1358
53
                                      {{EOFv, EOFv}, {0, UCharRangeMax}})}));
1359
53
  addToFunctionSummaryMap(
1360
53
      "getchar", Signature(ArgTypes{}, RetType{IntTy}),
1361
53
      Summary(NoEvalCall)
1362
53
          .Case({ReturnValueCondition(WithinRange,
1363
53
                                      {{EOFv, EOFv}, {0, UCharRangeMax}})}));
1364
1365
  // read()-like functions that never return more than buffer size.
1366
53
  auto FreadSummary =
1367
53
      Summary(NoEvalCall)
1368
53
          .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1369
53
                 ReturnValueCondition(WithinRange, Range(0, SizeMax))})
1370
53
          .ArgConstraint(NotNull(ArgNo(0)))
1371
53
          .ArgConstraint(NotNull(ArgNo(3)))
1372
53
          .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
1373
53
                                    /*BufSizeMultiplier=*/ArgNo(2)));
1374
1375
  // size_t fread(void *restrict ptr, size_t size, size_t nitems,
1376
  //              FILE *restrict stream);
1377
53
  addToFunctionSummaryMap(
1378
53
      "fread",
1379
53
      Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy},
1380
53
                RetType{SizeTy}),
1381
53
      FreadSummary);
1382
  // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems,
1383
  //               FILE *restrict stream);
1384
53
  addToFunctionSummaryMap("fwrite",
1385
53
                          Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy,
1386
53
                                             SizeTy, FilePtrRestrictTy},
1387
53
                                    RetType{SizeTy}),
1388
53
                          FreadSummary);
1389
1390
53
  Optional<QualType> Ssize_tTy = lookupTy("ssize_t");
1391
53
  Optional<RangeInt> Ssize_tMax = getMaxValue(Ssize_tTy);
1392
1393
53
  auto ReadSummary =
1394
53
      Summary(NoEvalCall)
1395
53
          .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1396
53
                 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
53
  addToFunctionSummaryMap(
1402
53
      "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1403
53
      ReadSummary);
1404
  // ssize_t write(int fildes, const void *buf, size_t nbyte);
1405
53
  addToFunctionSummaryMap(
1406
53
      "write",
1407
53
      Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}),
1408
53
      ReadSummary);
1409
1410
53
  auto GetLineSummary =
1411
53
      Summary(NoEvalCall)
1412
53
          .Case({ReturnValueCondition(WithinRange,
1413
53
                                      Range({-1, -1}, {1, Ssize_tMax}))});
1414
1415
53
  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
53
  addToFunctionSummaryMap(
1423
53
      "getline",
1424
53
      Signature(
1425
53
          ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, FilePtrRestrictTy},
1426
53
          RetType{Ssize_tTy}),
1427
53
      GetLineSummary);
1428
  // ssize_t getdelim(char **restrict lineptr, size_t *restrict n,
1429
  //                  int delimiter, FILE *restrict stream);
1430
53
  addToFunctionSummaryMap(
1431
53
      "getdelim",
1432
53
      Signature(ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, IntTy,
1433
53
                         FilePtrRestrictTy},
1434
53
                RetType{Ssize_tTy}),
1435
53
      GetLineSummary);
1436
1437
53
  {
1438
53
    Summary GetenvSummary = Summary(NoEvalCall)
1439
53
                                .ArgConstraint(NotNull(ArgNo(0)))
1440
53
                                .Case({NotNull(Ret)});
1441
    // In untrusted environments the envvar might not exist.
1442
53
    if (!ShouldAssumeControlledEnvironment)
1443
53
      GetenvSummary.Case({NotNull(Ret)->negate()});
1444
1445
    // char *getenv(const char *name);
1446
53
    addToFunctionSummaryMap(
1447
53
        "getenv", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1448
53
        std::move(GetenvSummary));
1449
53
  }
1450
1451
53
  if (ModelPOSIX) {
1452
1453
    // long a64l(const char *str64);
1454
7
    addToFunctionSummaryMap(
1455
7
        "a64l", Signature(ArgTypes{ConstCharPtrTy}, RetType{LongTy}),
1456
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1457
1458
    // char *l64a(long value);
1459
7
    addToFunctionSummaryMap("l64a",
1460
7
                            Signature(ArgTypes{LongTy}, RetType{CharPtrTy}),
1461
7
                            Summary(NoEvalCall)
1462
7
                                .ArgConstraint(ArgumentCondition(
1463
7
                                    0, WithinRange, Range(0, LongMax))));
1464
1465
7
    const auto ReturnsZeroOrMinusOne =
1466
7
        ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
1467
7
    const auto ReturnsFileDescriptor =
1468
7
        ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
1469
1470
    // int access(const char *pathname, int amode);
1471
7
    addToFunctionSummaryMap(
1472
7
        "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
1473
7
        Summary(NoEvalCall)
1474
7
            .Case(ReturnsZeroOrMinusOne)
1475
7
            .ArgConstraint(NotNull(ArgNo(0))));
1476
1477
    // int faccessat(int dirfd, const char *pathname, int mode, int flags);
1478
7
    addToFunctionSummaryMap(
1479
7
        "faccessat",
1480
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
1481
7
                  RetType{IntTy}),
1482
7
        Summary(NoEvalCall)
1483
7
            .Case(ReturnsZeroOrMinusOne)
1484
7
            .ArgConstraint(NotNull(ArgNo(1))));
1485
1486
    // int dup(int fildes);
1487
7
    addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1488
7
                            Summary(NoEvalCall)
1489
7
                                .Case(ReturnsFileDescriptor)
1490
7
                                .ArgConstraint(ArgumentCondition(
1491
7
                                    0, WithinRange, Range(0, IntMax))));
1492
1493
    // int dup2(int fildes1, int filedes2);
1494
7
    addToFunctionSummaryMap(
1495
7
        "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
1496
7
        Summary(NoEvalCall)
1497
7
            .Case(ReturnsFileDescriptor)
1498
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1499
7
            .ArgConstraint(
1500
7
                ArgumentCondition(1, WithinRange, Range(0, IntMax))));
1501
1502
    // int fdatasync(int fildes);
1503
7
    addToFunctionSummaryMap("fdatasync",
1504
7
                            Signature(ArgTypes{IntTy}, RetType{IntTy}),
1505
7
                            Summary(NoEvalCall)
1506
7
                                .Case(ReturnsZeroOrMinusOne)
1507
7
                                .ArgConstraint(ArgumentCondition(
1508
7
                                    0, WithinRange, Range(0, IntMax))));
1509
1510
    // int fnmatch(const char *pattern, const char *string, int flags);
1511
7
    addToFunctionSummaryMap(
1512
7
        "fnmatch",
1513
7
        Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy},
1514
7
                  RetType{IntTy}),
1515
7
        Summary(EvalCallAsPure)
1516
7
            .ArgConstraint(NotNull(ArgNo(0)))
1517
7
            .ArgConstraint(NotNull(ArgNo(1))));
1518
1519
    // int fsync(int fildes);
1520
7
    addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1521
7
                            Summary(NoEvalCall)
1522
7
                                .Case(ReturnsZeroOrMinusOne)
1523
7
                                .ArgConstraint(ArgumentCondition(
1524
7
                                    0, WithinRange, Range(0, IntMax))));
1525
1526
7
    Optional<QualType> Off_tTy = lookupTy("off_t");
1527
1528
    // int truncate(const char *path, off_t length);
1529
7
    addToFunctionSummaryMap(
1530
7
        "truncate",
1531
7
        Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
1532
7
        Summary(NoEvalCall)
1533
7
            .Case(ReturnsZeroOrMinusOne)
1534
7
            .ArgConstraint(NotNull(ArgNo(0))));
1535
1536
    // int symlink(const char *oldpath, const char *newpath);
1537
7
    addToFunctionSummaryMap(
1538
7
        "symlink",
1539
7
        Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
1540
7
        Summary(NoEvalCall)
1541
7
            .Case(ReturnsZeroOrMinusOne)
1542
7
            .ArgConstraint(NotNull(ArgNo(0)))
1543
7
            .ArgConstraint(NotNull(ArgNo(1))));
1544
1545
    // int symlinkat(const char *oldpath, int newdirfd, const char *newpath);
1546
7
    addToFunctionSummaryMap(
1547
7
        "symlinkat",
1548
7
        Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
1549
7
                  RetType{IntTy}),
1550
7
        Summary(NoEvalCall)
1551
7
            .Case(ReturnsZeroOrMinusOne)
1552
7
            .ArgConstraint(NotNull(ArgNo(0)))
1553
7
            .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
1554
7
            .ArgConstraint(NotNull(ArgNo(2))));
1555
1556
    // int lockf(int fd, int cmd, off_t len);
1557
7
    addToFunctionSummaryMap(
1558
7
        "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}),
1559
7
        Summary(NoEvalCall)
1560
7
            .Case(ReturnsZeroOrMinusOne)
1561
7
            .ArgConstraint(
1562
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1563
1564
7
    Optional<QualType> Mode_tTy = lookupTy("mode_t");
1565
1566
    // int creat(const char *pathname, mode_t mode);
1567
7
    addToFunctionSummaryMap(
1568
7
        "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1569
7
        Summary(NoEvalCall)
1570
7
            .Case(ReturnsFileDescriptor)
1571
7
            .ArgConstraint(NotNull(ArgNo(0))));
1572
1573
    // unsigned int sleep(unsigned int seconds);
1574
7
    addToFunctionSummaryMap(
1575
7
        "sleep", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
1576
7
        Summary(NoEvalCall)
1577
7
            .ArgConstraint(
1578
7
                ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1579
1580
7
    Optional<QualType> DirTy = lookupTy("DIR");
1581
7
    Optional<QualType> DirPtrTy = getPointerTy(DirTy);
1582
1583
    // int dirfd(DIR *dirp);
1584
7
    addToFunctionSummaryMap("dirfd",
1585
7
                            Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1586
7
                            Summary(NoEvalCall)
1587
7
                                .Case(ReturnsFileDescriptor)
1588
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1589
1590
    // unsigned int alarm(unsigned int seconds);
1591
7
    addToFunctionSummaryMap(
1592
7
        "alarm", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}),
1593
7
        Summary(NoEvalCall)
1594
7
            .ArgConstraint(
1595
7
                ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax))));
1596
1597
    // int closedir(DIR *dir);
1598
7
    addToFunctionSummaryMap("closedir",
1599
7
                            Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
1600
7
                            Summary(NoEvalCall)
1601
7
                                .Case(ReturnsZeroOrMinusOne)
1602
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1603
1604
    // char *strdup(const char *s);
1605
7
    addToFunctionSummaryMap(
1606
7
        "strdup", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}),
1607
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1608
1609
    // char *strndup(const char *s, size_t n);
1610
7
    addToFunctionSummaryMap(
1611
7
        "strndup",
1612
7
        Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}),
1613
7
        Summary(NoEvalCall)
1614
7
            .ArgConstraint(NotNull(ArgNo(0)))
1615
7
            .ArgConstraint(
1616
7
                ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1617
1618
    // wchar_t *wcsdup(const wchar_t *s);
1619
7
    addToFunctionSummaryMap(
1620
7
        "wcsdup", Signature(ArgTypes{ConstWchar_tPtrTy}, RetType{Wchar_tPtrTy}),
1621
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1622
1623
    // int mkstemp(char *template);
1624
7
    addToFunctionSummaryMap("mkstemp",
1625
7
                            Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
1626
7
                            Summary(NoEvalCall)
1627
7
                                .Case(ReturnsFileDescriptor)
1628
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1629
1630
    // char *mkdtemp(char *template);
1631
7
    addToFunctionSummaryMap(
1632
7
        "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
1633
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1634
1635
    // char *getcwd(char *buf, size_t size);
1636
7
    addToFunctionSummaryMap(
1637
7
        "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
1638
7
        Summary(NoEvalCall)
1639
7
            .ArgConstraint(
1640
7
                ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
1641
1642
    // int mkdir(const char *pathname, mode_t mode);
1643
7
    addToFunctionSummaryMap(
1644
7
        "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1645
7
        Summary(NoEvalCall)
1646
7
            .Case(ReturnsZeroOrMinusOne)
1647
7
            .ArgConstraint(NotNull(ArgNo(0))));
1648
1649
    // int mkdirat(int dirfd, const char *pathname, mode_t mode);
1650
7
    addToFunctionSummaryMap(
1651
7
        "mkdirat",
1652
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1653
7
        Summary(NoEvalCall)
1654
7
            .Case(ReturnsZeroOrMinusOne)
1655
7
            .ArgConstraint(NotNull(ArgNo(1))));
1656
1657
7
    Optional<QualType> Dev_tTy = lookupTy("dev_t");
1658
1659
    // int mknod(const char *pathname, mode_t mode, dev_t dev);
1660
7
    addToFunctionSummaryMap(
1661
7
        "mknod",
1662
7
        Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}),
1663
7
        Summary(NoEvalCall)
1664
7
            .Case(ReturnsZeroOrMinusOne)
1665
7
            .ArgConstraint(NotNull(ArgNo(0))));
1666
1667
    // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
1668
7
    addToFunctionSummaryMap(
1669
7
        "mknodat",
1670
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy},
1671
7
                  RetType{IntTy}),
1672
7
        Summary(NoEvalCall)
1673
7
            .Case(ReturnsZeroOrMinusOne)
1674
7
            .ArgConstraint(NotNull(ArgNo(1))));
1675
1676
    // int chmod(const char *path, mode_t mode);
1677
7
    addToFunctionSummaryMap(
1678
7
        "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
1679
7
        Summary(NoEvalCall)
1680
7
            .Case(ReturnsZeroOrMinusOne)
1681
7
            .ArgConstraint(NotNull(ArgNo(0))));
1682
1683
    // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
1684
7
    addToFunctionSummaryMap(
1685
7
        "fchmodat",
1686
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy},
1687
7
                  RetType{IntTy}),
1688
7
        Summary(NoEvalCall)
1689
7
            .Case(ReturnsZeroOrMinusOne)
1690
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1691
7
            .ArgConstraint(NotNull(ArgNo(1))));
1692
1693
    // int fchmod(int fildes, mode_t mode);
1694
7
    addToFunctionSummaryMap(
1695
7
        "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}),
1696
7
        Summary(NoEvalCall)
1697
7
            .Case(ReturnsZeroOrMinusOne)
1698
7
            .ArgConstraint(
1699
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1700
1701
7
    Optional<QualType> Uid_tTy = lookupTy("uid_t");
1702
7
    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
7
    addToFunctionSummaryMap(
1707
7
        "fchownat",
1708
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy},
1709
7
                  RetType{IntTy}),
1710
7
        Summary(NoEvalCall)
1711
7
            .Case(ReturnsZeroOrMinusOne)
1712
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1713
7
            .ArgConstraint(NotNull(ArgNo(1))));
1714
1715
    // int chown(const char *path, uid_t owner, gid_t group);
1716
7
    addToFunctionSummaryMap(
1717
7
        "chown",
1718
7
        Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1719
7
        Summary(NoEvalCall)
1720
7
            .Case(ReturnsZeroOrMinusOne)
1721
7
            .ArgConstraint(NotNull(ArgNo(0))));
1722
1723
    // int lchown(const char *path, uid_t owner, gid_t group);
1724
7
    addToFunctionSummaryMap(
1725
7
        "lchown",
1726
7
        Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1727
7
        Summary(NoEvalCall)
1728
7
            .Case(ReturnsZeroOrMinusOne)
1729
7
            .ArgConstraint(NotNull(ArgNo(0))));
1730
1731
    // int fchown(int fildes, uid_t owner, gid_t group);
1732
7
    addToFunctionSummaryMap(
1733
7
        "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
1734
7
        Summary(NoEvalCall)
1735
7
            .Case(ReturnsZeroOrMinusOne)
1736
7
            .ArgConstraint(
1737
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1738
1739
    // int rmdir(const char *pathname);
1740
7
    addToFunctionSummaryMap("rmdir",
1741
7
                            Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1742
7
                            Summary(NoEvalCall)
1743
7
                                .Case(ReturnsZeroOrMinusOne)
1744
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1745
1746
    // int chdir(const char *path);
1747
7
    addToFunctionSummaryMap("chdir",
1748
7
                            Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1749
7
                            Summary(NoEvalCall)
1750
7
                                .Case(ReturnsZeroOrMinusOne)
1751
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1752
1753
    // int link(const char *oldpath, const char *newpath);
1754
7
    addToFunctionSummaryMap(
1755
7
        "link",
1756
7
        Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
1757
7
        Summary(NoEvalCall)
1758
7
            .Case(ReturnsZeroOrMinusOne)
1759
7
            .ArgConstraint(NotNull(ArgNo(0)))
1760
7
            .ArgConstraint(NotNull(ArgNo(1))));
1761
1762
    // int linkat(int fd1, const char *path1, int fd2, const char *path2,
1763
    //            int flag);
1764
7
    addToFunctionSummaryMap(
1765
7
        "linkat",
1766
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy},
1767
7
                  RetType{IntTy}),
1768
7
        Summary(NoEvalCall)
1769
7
            .Case(ReturnsZeroOrMinusOne)
1770
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1771
7
            .ArgConstraint(NotNull(ArgNo(1)))
1772
7
            .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
1773
7
            .ArgConstraint(NotNull(ArgNo(3))));
1774
1775
    // int unlink(const char *pathname);
1776
7
    addToFunctionSummaryMap("unlink",
1777
7
                            Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
1778
7
                            Summary(NoEvalCall)
1779
7
                                .Case(ReturnsZeroOrMinusOne)
1780
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1781
1782
    // int unlinkat(int fd, const char *path, int flag);
1783
7
    addToFunctionSummaryMap(
1784
7
        "unlinkat",
1785
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}),
1786
7
        Summary(NoEvalCall)
1787
7
            .Case(ReturnsZeroOrMinusOne)
1788
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1789
7
            .ArgConstraint(NotNull(ArgNo(1))));
1790
1791
7
    Optional<QualType> StructStatTy = lookupTy("stat");
1792
7
    Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy);
1793
7
    Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy);
1794
1795
    // int fstat(int fd, struct stat *statbuf);
1796
7
    addToFunctionSummaryMap(
1797
7
        "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}),
1798
7
        Summary(NoEvalCall)
1799
7
            .Case(ReturnsZeroOrMinusOne)
1800
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1801
7
            .ArgConstraint(NotNull(ArgNo(1))));
1802
1803
    // int stat(const char *restrict path, struct stat *restrict buf);
1804
7
    addToFunctionSummaryMap(
1805
7
        "stat",
1806
7
        Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
1807
7
                  RetType{IntTy}),
1808
7
        Summary(NoEvalCall)
1809
7
            .Case(ReturnsZeroOrMinusOne)
1810
7
            .ArgConstraint(NotNull(ArgNo(0)))
1811
7
            .ArgConstraint(NotNull(ArgNo(1))));
1812
1813
    // int lstat(const char *restrict path, struct stat *restrict buf);
1814
7
    addToFunctionSummaryMap(
1815
7
        "lstat",
1816
7
        Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
1817
7
                  RetType{IntTy}),
1818
7
        Summary(NoEvalCall)
1819
7
            .Case(ReturnsZeroOrMinusOne)
1820
7
            .ArgConstraint(NotNull(ArgNo(0)))
1821
7
            .ArgConstraint(NotNull(ArgNo(1))));
1822
1823
    // int fstatat(int fd, const char *restrict path,
1824
    //             struct stat *restrict buf, int flag);
1825
7
    addToFunctionSummaryMap(
1826
7
        "fstatat",
1827
7
        Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy,
1828
7
                           StructStatPtrRestrictTy, IntTy},
1829
7
                  RetType{IntTy}),
1830
7
        Summary(NoEvalCall)
1831
7
            .Case(ReturnsZeroOrMinusOne)
1832
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1833
7
            .ArgConstraint(NotNull(ArgNo(1)))
1834
7
            .ArgConstraint(NotNull(ArgNo(2))));
1835
1836
    // DIR *opendir(const char *name);
1837
7
    addToFunctionSummaryMap(
1838
7
        "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
1839
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1840
1841
    // DIR *fdopendir(int fd);
1842
7
    addToFunctionSummaryMap("fdopendir",
1843
7
                            Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
1844
7
                            Summary(NoEvalCall)
1845
7
                                .ArgConstraint(ArgumentCondition(
1846
7
                                    0, WithinRange, Range(0, IntMax))));
1847
1848
    // int isatty(int fildes);
1849
7
    addToFunctionSummaryMap(
1850
7
        "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1851
7
        Summary(NoEvalCall)
1852
7
            .Case({ReturnValueCondition(WithinRange, Range(0, 1))})
1853
7
            .ArgConstraint(
1854
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1855
1856
    // FILE *popen(const char *command, const char *type);
1857
7
    addToFunctionSummaryMap(
1858
7
        "popen",
1859
7
        Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}),
1860
7
        Summary(NoEvalCall)
1861
7
            .ArgConstraint(NotNull(ArgNo(0)))
1862
7
            .ArgConstraint(NotNull(ArgNo(1))));
1863
1864
    // int pclose(FILE *stream);
1865
7
    addToFunctionSummaryMap(
1866
7
        "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1867
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1868
1869
    // int close(int fildes);
1870
7
    addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}),
1871
7
                            Summary(NoEvalCall)
1872
7
                                .Case(ReturnsZeroOrMinusOne)
1873
7
                                .ArgConstraint(ArgumentCondition(
1874
7
                                    0, WithinRange, Range(-1, IntMax))));
1875
1876
    // long fpathconf(int fildes, int name);
1877
7
    addToFunctionSummaryMap("fpathconf",
1878
7
                            Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}),
1879
7
                            Summary(NoEvalCall)
1880
7
                                .ArgConstraint(ArgumentCondition(
1881
7
                                    0, WithinRange, Range(0, IntMax))));
1882
1883
    // long pathconf(const char *path, int name);
1884
7
    addToFunctionSummaryMap(
1885
7
        "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}),
1886
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1887
1888
    // FILE *fdopen(int fd, const char *mode);
1889
7
    addToFunctionSummaryMap(
1890
7
        "fdopen",
1891
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}),
1892
7
        Summary(NoEvalCall)
1893
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1894
7
            .ArgConstraint(NotNull(ArgNo(1))));
1895
1896
    // void rewinddir(DIR *dir);
1897
7
    addToFunctionSummaryMap(
1898
7
        "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}),
1899
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1900
1901
    // void seekdir(DIR *dirp, long loc);
1902
7
    addToFunctionSummaryMap(
1903
7
        "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}),
1904
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1905
1906
    // int rand_r(unsigned int *seedp);
1907
7
    addToFunctionSummaryMap(
1908
7
        "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}),
1909
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
1910
1911
    // int fileno(FILE *stream);
1912
7
    addToFunctionSummaryMap("fileno",
1913
7
                            Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
1914
7
                            Summary(NoEvalCall)
1915
7
                                .Case(ReturnsFileDescriptor)
1916
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1917
1918
    // int fseeko(FILE *stream, off_t offset, int whence);
1919
7
    addToFunctionSummaryMap(
1920
7
        "fseeko",
1921
7
        Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
1922
7
        Summary(NoEvalCall)
1923
7
            .Case(ReturnsZeroOrMinusOne)
1924
7
            .ArgConstraint(NotNull(ArgNo(0))));
1925
1926
    // off_t ftello(FILE *stream);
1927
7
    addToFunctionSummaryMap(
1928
7
        "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}),
1929
7
        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
7
    addToFunctionSummaryMap(
1934
7
        "mmap",
1935
7
        Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
1936
7
                  RetType{VoidPtrTy}),
1937
7
        Summary(NoEvalCall)
1938
7
            .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1939
7
            .ArgConstraint(
1940
7
                ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
1941
1942
7
    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
7
    addToFunctionSummaryMap(
1946
7
        "mmap64",
1947
7
        Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
1948
7
                  RetType{VoidPtrTy}),
1949
7
        Summary(NoEvalCall)
1950
7
            .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax)))
1951
7
            .ArgConstraint(
1952
7
                ArgumentCondition(4, WithinRange, Range(-1, IntMax))));
1953
1954
    // int pipe(int fildes[2]);
1955
7
    addToFunctionSummaryMap("pipe",
1956
7
                            Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
1957
7
                            Summary(NoEvalCall)
1958
7
                                .Case(ReturnsZeroOrMinusOne)
1959
7
                                .ArgConstraint(NotNull(ArgNo(0))));
1960
1961
    // off_t lseek(int fildes, off_t offset, int whence);
1962
7
    addToFunctionSummaryMap(
1963
7
        "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}),
1964
7
        Summary(NoEvalCall)
1965
7
            .ArgConstraint(
1966
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
1967
1968
    // ssize_t readlink(const char *restrict path, char *restrict buf,
1969
    //                  size_t bufsize);
1970
7
    addToFunctionSummaryMap(
1971
7
        "readlink",
1972
7
        Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
1973
7
                  RetType{Ssize_tTy}),
1974
7
        Summary(NoEvalCall)
1975
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
1976
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
1977
7
            .ArgConstraint(NotNull(ArgNo(0)))
1978
7
            .ArgConstraint(NotNull(ArgNo(1)))
1979
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
1980
7
                                      /*BufSize=*/ArgNo(2)))
1981
7
            .ArgConstraint(
1982
7
                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
7
    addToFunctionSummaryMap(
1987
7
        "readlinkat",
1988
7
        Signature(
1989
7
            ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy},
1990
7
            RetType{Ssize_tTy}),
1991
7
        Summary(NoEvalCall)
1992
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
1993
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
1994
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
1995
7
            .ArgConstraint(NotNull(ArgNo(1)))
1996
7
            .ArgConstraint(NotNull(ArgNo(2)))
1997
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2),
1998
7
                                      /*BufSize=*/ArgNo(3)))
1999
7
            .ArgConstraint(
2000
7
                ArgumentCondition(3, WithinRange, Range(0, SizeMax))));
2001
2002
    // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char
2003
    // *newpath);
2004
7
    addToFunctionSummaryMap(
2005
7
        "renameat",
2006
7
        Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy},
2007
7
                  RetType{IntTy}),
2008
7
        Summary(NoEvalCall)
2009
7
            .Case(ReturnsZeroOrMinusOne)
2010
7
            .ArgConstraint(NotNull(ArgNo(1)))
2011
7
            .ArgConstraint(NotNull(ArgNo(3))));
2012
2013
    // char *realpath(const char *restrict file_name,
2014
    //                char *restrict resolved_name);
2015
7
    addToFunctionSummaryMap(
2016
7
        "realpath",
2017
7
        Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
2018
7
                  RetType{CharPtrTy}),
2019
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2020
2021
7
    QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy));
2022
2023
    // int execv(const char *path, char *const argv[]);
2024
7
    addToFunctionSummaryMap(
2025
7
        "execv",
2026
7
        Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2027
7
        Summary(NoEvalCall)
2028
7
            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
2029
7
            .ArgConstraint(NotNull(ArgNo(0))));
2030
2031
    // int execvp(const char *file, char *const argv[]);
2032
7
    addToFunctionSummaryMap(
2033
7
        "execvp",
2034
7
        Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
2035
7
        Summary(NoEvalCall)
2036
7
            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
2037
7
            .ArgConstraint(NotNull(ArgNo(0))));
2038
2039
    // int getopt(int argc, char * const argv[], const char *optstring);
2040
7
    addToFunctionSummaryMap(
2041
7
        "getopt",
2042
7
        Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
2043
7
                  RetType{IntTy}),
2044
7
        Summary(NoEvalCall)
2045
7
            .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))})
2046
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2047
7
            .ArgConstraint(NotNull(ArgNo(1)))
2048
7
            .ArgConstraint(NotNull(ArgNo(2))));
2049
2050
7
    Optional<QualType> StructSockaddrTy = lookupTy("sockaddr");
2051
7
    Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy);
2052
7
    Optional<QualType> ConstStructSockaddrPtrTy =
2053
7
        getPointerTy(getConstTy(StructSockaddrTy));
2054
7
    Optional<QualType> StructSockaddrPtrRestrictTy =
2055
7
        getRestrictTy(StructSockaddrPtrTy);
2056
7
    Optional<QualType> ConstStructSockaddrPtrRestrictTy =
2057
7
        getRestrictTy(ConstStructSockaddrPtrTy);
2058
7
    Optional<QualType> Socklen_tTy = lookupTy("socklen_t");
2059
7
    Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy);
2060
7
    Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy);
2061
7
    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
7
    auto Accept =
2070
7
        Summary(NoEvalCall)
2071
7
            .Case(ReturnsFileDescriptor)
2072
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
2073
7
    if (!addToFunctionSummaryMap(
2074
7
            "accept",
2075
            // int accept(int socket, struct sockaddr *restrict address,
2076
            //            socklen_t *restrict address_len);
2077
7
            Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2078
7
                               Socklen_tPtrRestrictTy},
2079
7
                      RetType{IntTy}),
2080
7
            Accept))
2081
6
      addToFunctionSummaryMap(
2082
6
          "accept",
2083
6
          Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2084
6
                    RetType{IntTy}),
2085
6
          Accept);
2086
2087
    // int bind(int socket, const struct sockaddr *address, socklen_t
2088
    //          address_len);
2089
7
    if (!addToFunctionSummaryMap(
2090
7
            "bind",
2091
7
            Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
2092
7
                      RetType{IntTy}),
2093
7
            Summary(NoEvalCall)
2094
7
                .Case(ReturnsZeroOrMinusOne)
2095
7
                .ArgConstraint(
2096
7
                    ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2097
7
                .ArgConstraint(NotNull(ArgNo(1)))
2098
7
                .ArgConstraint(
2099
7
                    BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2)))
2100
7
                .ArgConstraint(
2101
7
                    ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))))
2102
      // Do not add constraints on sockaddr.
2103
6
      addToFunctionSummaryMap(
2104
6
          "bind",
2105
6
          Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
2106
6
          Summary(NoEvalCall)
2107
6
              .Case(ReturnsZeroOrMinusOne)
2108
6
              .ArgConstraint(
2109
6
                  ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2110
6
              .ArgConstraint(
2111
6
                  ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))));
2112
2113
    // int getpeername(int socket, struct sockaddr *restrict address,
2114
    //                 socklen_t *restrict address_len);
2115
7
    if (!addToFunctionSummaryMap(
2116
7
            "getpeername",
2117
7
            Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2118
7
                               Socklen_tPtrRestrictTy},
2119
7
                      RetType{IntTy}),
2120
7
            Summary(NoEvalCall)
2121
7
                .Case(ReturnsZeroOrMinusOne)
2122
7
                .ArgConstraint(
2123
7
                    ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2124
7
                .ArgConstraint(NotNull(ArgNo(1)))
2125
7
                .ArgConstraint(NotNull(ArgNo(2)))))
2126
6
      addToFunctionSummaryMap(
2127
6
          "getpeername",
2128
6
          Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2129
6
                    RetType{IntTy}),
2130
6
          Summary(NoEvalCall)
2131
6
              .Case(ReturnsZeroOrMinusOne)
2132
6
              .ArgConstraint(
2133
6
                  ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2134
2135
    // int getsockname(int socket, struct sockaddr *restrict address,
2136
    //                 socklen_t *restrict address_len);
2137
7
    if (!addToFunctionSummaryMap(
2138
7
            "getsockname",
2139
7
            Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy,
2140
7
                               Socklen_tPtrRestrictTy},
2141
7
                      RetType{IntTy}),
2142
7
            Summary(NoEvalCall)
2143
7
                .Case(ReturnsZeroOrMinusOne)
2144
7
                .ArgConstraint(
2145
7
                    ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2146
7
                .ArgConstraint(NotNull(ArgNo(1)))
2147
7
                .ArgConstraint(NotNull(ArgNo(2)))))
2148
6
      addToFunctionSummaryMap(
2149
6
          "getsockname",
2150
6
          Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
2151
6
                    RetType{IntTy}),
2152
6
          Summary(NoEvalCall)
2153
6
              .Case(ReturnsZeroOrMinusOne)
2154
6
              .ArgConstraint(
2155
6
                  ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2156
2157
    // int connect(int socket, const struct sockaddr *address, socklen_t
2158
    //             address_len);
2159
7
    if (!addToFunctionSummaryMap(
2160
7
            "connect",
2161
7
            Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
2162
7
                      RetType{IntTy}),
2163
7
            Summary(NoEvalCall)
2164
7
                .Case(ReturnsZeroOrMinusOne)
2165
7
                .ArgConstraint(
2166
7
                    ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2167
7
                .ArgConstraint(NotNull(ArgNo(1)))))
2168
6
      addToFunctionSummaryMap(
2169
6
          "connect",
2170
6
          Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
2171
6
          Summary(NoEvalCall)
2172
6
              .Case(ReturnsZeroOrMinusOne)
2173
6
              .ArgConstraint(
2174
6
                  ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2175
2176
7
    auto Recvfrom =
2177
7
        Summary(NoEvalCall)
2178
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2179
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2180
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2181
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2182
7
                                      /*BufSize=*/ArgNo(2)));
2183
7
    if (!addToFunctionSummaryMap(
2184
7
            "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
7
            Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2190
7
                               StructSockaddrPtrRestrictTy,
2191
7
                               Socklen_tPtrRestrictTy},
2192
7
                      RetType{Ssize_tTy}),
2193
7
            Recvfrom))
2194
6
      addToFunctionSummaryMap(
2195
6
          "recvfrom",
2196
6
          Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy,
2197
6
                             Irrelevant, Socklen_tPtrRestrictTy},
2198
6
                    RetType{Ssize_tTy}),
2199
6
          Recvfrom);
2200
2201
7
    auto Sendto =
2202
7
        Summary(NoEvalCall)
2203
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2204
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2205
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2206
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2207
7
                                      /*BufSize=*/ArgNo(2)));
2208
7
    if (!addToFunctionSummaryMap(
2209
7
            "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
7
            Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy,
2214
7
                               ConstStructSockaddrPtrTy, Socklen_tTy},
2215
7
                      RetType{Ssize_tTy}),
2216
7
            Sendto))
2217
6
      addToFunctionSummaryMap(
2218
6
          "sendto",
2219
6
          Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant,
2220
6
                             Socklen_tTy},
2221
6
                    RetType{Ssize_tTy}),
2222
6
          Sendto);
2223
2224
    // int listen(int sockfd, int backlog);
2225
7
    addToFunctionSummaryMap("listen",
2226
7
                            Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
2227
7
                            Summary(NoEvalCall)
2228
7
                                .Case(ReturnsZeroOrMinusOne)
2229
7
                                .ArgConstraint(ArgumentCondition(
2230
7
                                    0, WithinRange, Range(0, IntMax))));
2231
2232
    // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
2233
7
    addToFunctionSummaryMap(
2234
7
        "recv",
2235
7
        Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy},
2236
7
                  RetType{Ssize_tTy}),
2237
7
        Summary(NoEvalCall)
2238
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2239
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2240
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2241
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2242
7
                                      /*BufSize=*/ArgNo(2))));
2243
2244
7
    Optional<QualType> StructMsghdrTy = lookupTy("msghdr");
2245
7
    Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy);
2246
7
    Optional<QualType> ConstStructMsghdrPtrTy =
2247
7
        getPointerTy(getConstTy(StructMsghdrTy));
2248
2249
    // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
2250
7
    addToFunctionSummaryMap(
2251
7
        "recvmsg",
2252
7
        Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
2253
7
                  RetType{Ssize_tTy}),
2254
7
        Summary(NoEvalCall)
2255
7
            .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2256
7
            .ArgConstraint(
2257
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2258
2259
    // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
2260
7
    addToFunctionSummaryMap(
2261
7
        "sendmsg",
2262
7
        Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
2263
7
                  RetType{Ssize_tTy}),
2264
7
        Summary(NoEvalCall)
2265
7
            .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2266
7
            .ArgConstraint(
2267
7
                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
7
    addToFunctionSummaryMap(
2272
7
        "setsockopt",
2273
7
        Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
2274
7
                  RetType{IntTy}),
2275
7
        Summary(NoEvalCall)
2276
7
            .Case(ReturnsZeroOrMinusOne)
2277
7
            .ArgConstraint(NotNull(ArgNo(3)))
2278
7
            .ArgConstraint(
2279
7
                BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
2280
7
            .ArgConstraint(
2281
7
                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
7
    addToFunctionSummaryMap(
2287
7
        "getsockopt",
2288
7
        Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy,
2289
7
                           Socklen_tPtrRestrictTy},
2290
7
                  RetType{IntTy}),
2291
7
        Summary(NoEvalCall)
2292
7
            .Case(ReturnsZeroOrMinusOne)
2293
7
            .ArgConstraint(NotNull(ArgNo(3)))
2294
7
            .ArgConstraint(NotNull(ArgNo(4))));
2295
2296
    // ssize_t send(int sockfd, const void *buf, size_t len, int flags);
2297
7
    addToFunctionSummaryMap(
2298
7
        "send",
2299
7
        Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy},
2300
7
                  RetType{Ssize_tTy}),
2301
7
        Summary(NoEvalCall)
2302
7
            .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
2303
7
                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
2304
7
            .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
2305
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2306
7
                                      /*BufSize=*/ArgNo(2))));
2307
2308
    // int socketpair(int domain, int type, int protocol, int sv[2]);
2309
7
    addToFunctionSummaryMap(
2310
7
        "socketpair",
2311
7
        Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}),
2312
7
        Summary(NoEvalCall)
2313
7
            .Case(ReturnsZeroOrMinusOne)
2314
7
            .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
7
    addToFunctionSummaryMap(
2324
7
        "getnameinfo",
2325
7
        Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy,
2326
7
                           CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy,
2327
7
                           Socklen_tTy, IntTy},
2328
7
                  RetType{IntTy}),
2329
7
        Summary(NoEvalCall)
2330
7
            .ArgConstraint(
2331
7
                BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))
2332
7
            .ArgConstraint(
2333
7
                ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax)))
2334
7
            .ArgConstraint(
2335
7
                BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3)))
2336
7
            .ArgConstraint(
2337
7
                ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax)))
2338
7
            .ArgConstraint(
2339
7
                BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5)))
2340
7
            .ArgConstraint(
2341
7
                ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax))));
2342
2343
7
    Optional<QualType> StructUtimbufTy = lookupTy("utimbuf");
2344
7
    Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy);
2345
2346
    // int utime(const char *filename, struct utimbuf *buf);
2347
7
    addToFunctionSummaryMap(
2348
7
        "utime",
2349
7
        Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}),
2350
7
        Summary(NoEvalCall)
2351
7
            .Case(ReturnsZeroOrMinusOne)
2352
7
            .ArgConstraint(NotNull(ArgNo(0))));
2353
2354
7
    Optional<QualType> StructTimespecTy = lookupTy("timespec");
2355
7
    Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy);
2356
7
    Optional<QualType> ConstStructTimespecPtrTy =
2357
7
        getPointerTy(getConstTy(StructTimespecTy));
2358
2359
    // int futimens(int fd, const struct timespec times[2]);
2360
7
    addToFunctionSummaryMap(
2361
7
        "futimens",
2362
7
        Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}),
2363
7
        Summary(NoEvalCall)
2364
7
            .Case(ReturnsZeroOrMinusOne)
2365
7
            .ArgConstraint(
2366
7
                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
2367
2368
    // int utimensat(int dirfd, const char *pathname,
2369
    //               const struct timespec times[2], int flags);
2370
7
    addToFunctionSummaryMap("utimensat",
2371
7
                            Signature(ArgTypes{IntTy, ConstCharPtrTy,
2372
7
                                               ConstStructTimespecPtrTy, IntTy},
2373
7
                                      RetType{IntTy}),
2374
7
                            Summary(NoEvalCall)
2375
7
                                .Case(ReturnsZeroOrMinusOne)
2376
7
                                .ArgConstraint(NotNull(ArgNo(1))));
2377
2378
7
    Optional<QualType> StructTimevalTy = lookupTy("timeval");
2379
7
    Optional<QualType> ConstStructTimevalPtrTy =
2380
7
        getPointerTy(getConstTy(StructTimevalTy));
2381
2382
    // int utimes(const char *filename, const struct timeval times[2]);
2383
7
    addToFunctionSummaryMap(
2384
7
        "utimes",
2385
7
        Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
2386
7
                  RetType{IntTy}),
2387
7
        Summary(NoEvalCall)
2388
7
            .Case(ReturnsZeroOrMinusOne)
2389
7
            .ArgConstraint(NotNull(ArgNo(0))));
2390
2391
    // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
2392
7
    addToFunctionSummaryMap(
2393
7
        "nanosleep",
2394
7
        Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
2395
7
                  RetType{IntTy}),
2396
7
        Summary(NoEvalCall)
2397
7
            .Case(ReturnsZeroOrMinusOne)
2398
7
            .ArgConstraint(NotNull(ArgNo(0))));
2399
2400
7
    Optional<QualType> Time_tTy = lookupTy("time_t");
2401
7
    Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy));
2402
7
    Optional<QualType> ConstTime_tPtrRestrictTy =
2403
7
        getRestrictTy(ConstTime_tPtrTy);
2404
2405
7
    Optional<QualType> StructTmTy = lookupTy("tm");
2406
7
    Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy);
2407
7
    Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy);
2408
7
    Optional<QualType> ConstStructTmPtrTy =
2409
7
        getPointerTy(getConstTy(StructTmTy));
2410
7
    Optional<QualType> ConstStructTmPtrRestrictTy =
2411
7
        getRestrictTy(ConstStructTmPtrTy);
2412
2413
    // struct tm * localtime(const time_t *tp);
2414
7
    addToFunctionSummaryMap(
2415
7
        "localtime",
2416
7
        Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
2417
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2418
2419
    // struct tm *localtime_r(const time_t *restrict timer,
2420
    //                        struct tm *restrict result);
2421
7
    addToFunctionSummaryMap(
2422
7
        "localtime_r",
2423
7
        Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2424
7
                  RetType{StructTmPtrTy}),
2425
7
        Summary(NoEvalCall)
2426
7
            .ArgConstraint(NotNull(ArgNo(0)))
2427
7
            .ArgConstraint(NotNull(ArgNo(1))));
2428
2429
    // char *asctime_r(const struct tm *restrict tm, char *restrict buf);
2430
7
    addToFunctionSummaryMap(
2431
7
        "asctime_r",
2432
7
        Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy},
2433
7
                  RetType{CharPtrTy}),
2434
7
        Summary(NoEvalCall)
2435
7
            .ArgConstraint(NotNull(ArgNo(0)))
2436
7
            .ArgConstraint(NotNull(ArgNo(1)))
2437
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
2438
7
                                      /*MinBufSize=*/BVF.getValue(26, IntTy))));
2439
2440
    // char *ctime_r(const time_t *timep, char *buf);
2441
7
    addToFunctionSummaryMap(
2442
7
        "ctime_r",
2443
7
        Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}),
2444
7
        Summary(NoEvalCall)
2445
7
            .ArgConstraint(NotNull(ArgNo(0)))
2446
7
            .ArgConstraint(NotNull(ArgNo(1)))
2447
7
            .ArgConstraint(BufferSize(
2448
7
                /*Buffer=*/ArgNo(1),
2449
7
                /*MinBufSize=*/BVF.getValue(26, IntTy))));
2450
2451
    // struct tm *gmtime_r(const time_t *restrict timer,
2452
    //                     struct tm *restrict result);
2453
7
    addToFunctionSummaryMap(
2454
7
        "gmtime_r",
2455
7
        Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy},
2456
7
                  RetType{StructTmPtrTy}),
2457
7
        Summary(NoEvalCall)
2458
7
            .ArgConstraint(NotNull(ArgNo(0)))
2459
7
            .ArgConstraint(NotNull(ArgNo(1))));
2460
2461
    // struct tm * gmtime(const time_t *tp);
2462
7
    addToFunctionSummaryMap(
2463
7
        "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}),
2464
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2465
2466
7
    Optional<QualType> Clockid_tTy = lookupTy("clockid_t");
2467
2468
    // int clock_gettime(clockid_t clock_id, struct timespec *tp);
2469
7
    addToFunctionSummaryMap(
2470
7
        "clock_gettime",
2471
7
        Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}),
2472
7
        Summary(NoEvalCall)
2473
7
            .Case(ReturnsZeroOrMinusOne)
2474
7
            .ArgConstraint(NotNull(ArgNo(1))));
2475
2476
7
    Optional<QualType> StructItimervalTy = lookupTy("itimerval");
2477
7
    Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy);
2478
2479
    // int getitimer(int which, struct itimerval *curr_value);
2480
7
    addToFunctionSummaryMap(
2481
7
        "getitimer",
2482
7
        Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}),
2483
7
        Summary(NoEvalCall)
2484
7
            .Case(ReturnsZeroOrMinusOne)
2485
7
            .ArgConstraint(NotNull(ArgNo(1))));
2486
2487
7
    Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
2488
7
    Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy);
2489
7
    Optional<QualType> Pthread_tTy = lookupTy("pthread_t");
2490
7
    Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy);
2491
7
    Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy);
2492
7
    Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t");
2493
7
    Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy);
2494
7
    Optional<QualType> Pthread_mutex_tPtrRestrictTy =
2495
7
        getRestrictTy(Pthread_mutex_tPtrTy);
2496
7
    Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t");
2497
7
    Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy);
2498
7
    Optional<QualType> ConstPthread_attr_tPtrTy =
2499
7
        getPointerTy(getConstTy(Pthread_attr_tTy));
2500
7
    Optional<QualType> ConstPthread_attr_tPtrRestrictTy =
2501
7
        getRestrictTy(ConstPthread_attr_tPtrTy);
2502
7
    Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t");
2503
7
    Optional<QualType> ConstPthread_mutexattr_tPtrTy =
2504
7
        getPointerTy(getConstTy(Pthread_mutexattr_tTy));
2505
7
    Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy =
2506
7
        getRestrictTy(ConstPthread_mutexattr_tPtrTy);
2507
2508
7
    QualType PthreadStartRoutineTy = getPointerTy(
2509
7
        ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy,
2510
7
                             FunctionProtoType::ExtProtoInfo()));
2511
2512
    // int pthread_cond_signal(pthread_cond_t *cond);
2513
    // int pthread_cond_broadcast(pthread_cond_t *cond);
2514
7
    addToFunctionSummaryMap(
2515
7
        {"pthread_cond_signal", "pthread_cond_broadcast"},
2516
7
        Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}),
2517
7
        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
7
    addToFunctionSummaryMap(
2523
7
        "pthread_create",
2524
7
        Signature(ArgTypes{Pthread_tPtrRestrictTy,
2525
7
                           ConstPthread_attr_tPtrRestrictTy,
2526
7
                           PthreadStartRoutineTy, VoidPtrRestrictTy},
2527
7
                  RetType{IntTy}),
2528
7
        Summary(NoEvalCall)
2529
7
            .ArgConstraint(NotNull(ArgNo(0)))
2530
7
            .ArgConstraint(NotNull(ArgNo(2))));
2531
2532
    // int pthread_attr_destroy(pthread_attr_t *attr);
2533
    // int pthread_attr_init(pthread_attr_t *attr);
2534
7
    addToFunctionSummaryMap(
2535
7
        {"pthread_attr_destroy", "pthread_attr_init"},
2536
7
        Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}),
2537
7
        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
7
    addToFunctionSummaryMap(
2544
7
        {"pthread_attr_getstacksize", "pthread_attr_getguardsize"},
2545
7
        Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy},
2546
7
                  RetType{IntTy}),
2547
7
        Summary(NoEvalCall)
2548
7
            .ArgConstraint(NotNull(ArgNo(0)))
2549
7
            .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
7
    addToFunctionSummaryMap(
2554
7
        {"pthread_attr_setstacksize", "pthread_attr_setguardsize"},
2555
7
        Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}),
2556
7
        Summary(NoEvalCall)
2557
7
            .ArgConstraint(NotNull(ArgNo(0)))
2558
7
            .ArgConstraint(
2559
7
                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
7
    addToFunctionSummaryMap(
2564
7
        "pthread_mutex_init",
2565
7
        Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy,
2566
7
                           ConstPthread_mutexattr_tPtrRestrictTy},
2567
7
                  RetType{IntTy}),
2568
7
        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
7
    addToFunctionSummaryMap(
2575
7
        {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock",
2576
7
         "pthread_mutex_unlock"},
2577
7
        Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}),
2578
7
        Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
2579
7
  }
2580
2581
  // Functions for testing.
2582
53
  if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) {
2583
7
    addToFunctionSummaryMap(
2584
7
        "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
2585
7
        Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2586
2587
    // Test range values.
2588
7
    addToFunctionSummaryMap(
2589
7
        "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2590
7
        Summary(EvalCallAsPure)
2591
7
            .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2592
7
    addToFunctionSummaryMap(
2593
7
        "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2594
7
        Summary(EvalCallAsPure)
2595
7
            .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2))));
2596
7
    addToFunctionSummaryMap("__range_1_2__4_5",
2597
7
                            Signature(ArgTypes{IntTy}, RetType{IntTy}),
2598
7
                            Summary(EvalCallAsPure)
2599
7
                                .ArgConstraint(ArgumentCondition(
2600
7
                                    0U, WithinRange, Range({1, 2}, {4, 5}))));
2601
2602
    // Test range kind.
2603
7
    addToFunctionSummaryMap(
2604
7
        "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2605
7
        Summary(EvalCallAsPure)
2606
7
            .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))));
2607
7
    addToFunctionSummaryMap(
2608
7
        "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2609
7
        Summary(EvalCallAsPure)
2610
7
            .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))));
2611
2612
7
    addToFunctionSummaryMap(
2613
7
        "__two_constrained_args",
2614
7
        Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
2615
7
        Summary(EvalCallAsPure)
2616
7
            .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))
2617
7
            .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1))));
2618
7
    addToFunctionSummaryMap(
2619
7
        "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}),
2620
7
        Summary(EvalCallAsPure)
2621
7
            .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))
2622
7
            .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2))));
2623
7
    addToFunctionSummaryMap(
2624
7
        "__defaultparam",
2625
7
        Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}),
2626
7
        Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0))));
2627
7
    addToFunctionSummaryMap(
2628
7
        "__variadic",
2629
7
        Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}),
2630
7
        Summary(EvalCallAsPure)
2631
7
            .ArgConstraint(NotNull(ArgNo(0)))
2632
7
            .ArgConstraint(NotNull(ArgNo(1))));
2633
7
    addToFunctionSummaryMap(
2634
7
        "__buf_size_arg_constraint",
2635
7
        Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}),
2636
7
        Summary(EvalCallAsPure)
2637
7
            .ArgConstraint(
2638
7
                BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))));
2639
7
    addToFunctionSummaryMap(
2640
7
        "__buf_size_arg_constraint_mul",
2641
7
        Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}),
2642
7
        Summary(EvalCallAsPure)
2643
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
2644
7
                                      /*BufSizeMultiplier=*/ArgNo(2))));
2645
7
    addToFunctionSummaryMap(
2646
7
        "__buf_size_arg_constraint_concrete",
2647
7
        Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}),
2648
7
        Summary(EvalCallAsPure)
2649
7
            .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0),
2650
7
                                      /*BufSize=*/BVF.getValue(10, IntTy))));
2651
7
    addToFunctionSummaryMap(
2652
7
        {"__test_restrict_param_0", "__test_restrict_param_1",
2653
7
         "__test_restrict_param_2"},
2654
7
        Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}),
2655
7
        Summary(EvalCallAsPure));
2656
7
  }
2657
2658
53
  SummariesInitialized = true;
2659
53
}
2660
2661
79
void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
2662
79
  auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>();
2663
79
  const AnalyzerOptions &Opts = mgr.getAnalyzerOptions();
2664
79
  Checker->DisplayLoadedSummaries =
2665
79
      Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries");
2666
79
  Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX");
2667
79
  Checker->ShouldAssumeControlledEnvironment =
2668
79
      Opts.ShouldAssumeControlledEnvironment;
2669
79
}
2670
2671
bool ento::shouldRegisterStdCLibraryFunctionsChecker(
2672
194
    const CheckerManager &mgr) {
2673
194
  return true;
2674
194
}
2675
2676
#define REGISTER_CHECKER(name)                                                 \
2677
19
  void ento::register##name(CheckerManager &mgr) {                             \
2678
19
    StdLibraryFunctionsChecker *checker =                                      \
2679
19
        mgr.getChecker<StdLibraryFunctionsChecker>();                          \
2680
19
    checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
2681
19
    checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
2682
19
        mgr.getCurrentCheckerName();                                           \
2683
19
  }                                                                            \
clang::ento::registerStdCLibraryFunctionArgsChecker(clang::ento::CheckerManager&)
Line
Count
Source
2677
12
  void ento::register##name(CheckerManager &mgr) {                             \
2678
12
    StdLibraryFunctionsChecker *checker =                                      \
2679
12
        mgr.getChecker<StdLibraryFunctionsChecker>();                          \
2680
12
    checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
2681
12
    checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
2682
12
        mgr.getCurrentCheckerName();                                           \
2683
12
  }                                                                            \
clang::ento::registerStdCLibraryFunctionsTesterChecker(clang::ento::CheckerManager&)
Line
Count
Source
2677
7
  void ento::register##name(CheckerManager &mgr) {                             \
2678
7
    StdLibraryFunctionsChecker *checker =                                      \
2679
7
        mgr.getChecker<StdLibraryFunctionsChecker>();                          \
2680
7
    checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true;      \
2681
7
    checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] =               \
2682
7
        mgr.getCurrentCheckerName();                                           \
2683
7
  }                                                                            \
2684
                                                                               \
2685
40
  bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
clang::ento::shouldRegisterStdCLibraryFunctionArgsChecker(clang::ento::CheckerManager const&)
Line
Count
Source
2685
26
  bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
clang::ento::shouldRegisterStdCLibraryFunctionsTesterChecker(clang::ento::CheckerManager const&)
Line
Count
Source
2685
14
  bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; }
2686
2687
REGISTER_CHECKER(StdCLibraryFunctionArgsChecker)
2688
REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker)