clang  6.0.0svn
StdLibraryFunctionsChecker.cpp
Go to the documentation of this file.
1 //=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This checker improves modeling of a few simple library functions.
11 // It does not generate warnings.
12 //
13 // This checker provides a specification format - `FunctionSummaryTy' - and
14 // contains descriptions of some library functions in this format. Each
15 // specification contains a list of branches for splitting the program state
16 // upon call, and range constraints on argument and return-value symbols that
17 // are satisfied on each branch. This spec can be expanded to include more
18 // items, like external effects of the function.
19 //
20 // The main difference between this approach and the body farms technique is
21 // in more explicit control over how many branches are produced. For example,
22 // consider standard C function `ispunct(int x)', which returns a non-zero value
23 // iff `x' is a punctuation character, that is, when `x' is in range
24 // ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~'].
25 // `FunctionSummaryTy' provides only two branches for this function. However,
26 // any attempt to describe this range with if-statements in the body farm
27 // would result in many more branches. Because each branch needs to be analyzed
28 // independently, this significantly reduces performance. Additionally,
29 // once we consider a branch on which `x' is in range, say, ['!', '/'],
30 // we assume that such branch is an important separate path through the program,
31 // which may lead to false positives because considering this particular path
32 // was not consciously intended, and therefore it might have been unreachable.
33 //
34 // This checker uses eval::Call for modeling "pure" functions, for which
35 // their `FunctionSummaryTy' is a precise model. This avoids unnecessary
36 // invalidation passes. Conflicts with other checkers are unlikely because
37 // if the function has no other effects, other checkers would probably never
38 // want to improve upon the modeling done by this checker.
39 //
40 // Non-"pure" functions, for which only partial improvement over the default
41 // behavior is expected, are modeled via check::PostCall, non-intrusively.
42 //
43 // The following standard C functions are currently supported:
44 //
45 // fgetc getline isdigit isupper
46 // fread isalnum isgraph isxdigit
47 // fwrite isalpha islower read
48 // getc isascii isprint write
49 // getchar isblank ispunct
50 // getdelim iscntrl isspace
51 //
52 //===----------------------------------------------------------------------===//
53 
54 #include "ClangSACheckers.h"
59 
60 using namespace clang;
61 using namespace clang::ento;
62 
63 namespace {
64 class StdLibraryFunctionsChecker : public Checker<check::PostCall, eval::Call> {
65  /// Below is a series of typedefs necessary to define function specs.
66  /// We avoid nesting types here because each additional qualifier
67  /// would need to be repeated in every function spec.
68  struct FunctionSummaryTy;
69 
70  /// Specify how much the analyzer engine should entrust modeling this function
71  /// to us. If he doesn't, he performs additional invalidations.
72  enum InvalidationKindTy { NoEvalCall, EvalCallAsPure };
73 
74  /// A pair of ValueRangeKindTy and IntRangeVectorTy would describe a range
75  /// imposed on a particular argument or return value symbol.
76  ///
77  /// Given a range, should the argument stay inside or outside this range?
78  /// The special `ComparesToArgument' value indicates that we should
79  /// impose a constraint that involves other argument or return value symbols.
80  enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument };
81 
82  // The universal integral type to use in value range descriptions.
83  // Unsigned to make sure overflows are well-defined.
84  typedef uint64_t RangeIntTy;
85 
86  /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is
87  /// a non-negative integer, which less than 5 and not equal to 2. For
88  /// `ComparesToArgument', holds information about how exactly to compare to
89  /// the argument.
90  typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy;
91 
92  /// A reference to an argument or return value by its number.
93  /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but
94  /// obviously uint32_t should be enough for all practical purposes.
95  typedef uint32_t ArgNoTy;
96  static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max();
97 
98  /// Incapsulates a single range on a single symbol within a branch.
99  class ValueRange {
100  ArgNoTy ArgNo; // Argument to which we apply the range.
101  ValueRangeKindTy Kind; // Kind of range definition.
102  IntRangeVectorTy Args; // Polymorphic arguments.
103 
104  public:
105  ValueRange(ArgNoTy ArgNo, ValueRangeKindTy Kind,
106  const IntRangeVectorTy &Args)
107  : ArgNo(ArgNo), Kind(Kind), Args(Args) {}
108 
109  ArgNoTy getArgNo() const { return ArgNo; }
110  ValueRangeKindTy getKind() const { return Kind; }
111 
113  assert(Kind == ComparesToArgument);
114  assert(Args.size() == 1);
116  static_cast<BinaryOperator::Opcode>(Args[0].first);
117  assert(BinaryOperator::isComparisonOp(Op) &&
118  "Only comparison ops are supported for ComparesToArgument");
119  return Op;
120  }
121 
122  ArgNoTy getOtherArgNo() const {
123  assert(Kind == ComparesToArgument);
124  assert(Args.size() == 1);
125  return static_cast<ArgNoTy>(Args[0].second);
126  }
127 
128  const IntRangeVectorTy &getRanges() const {
129  assert(Kind != ComparesToArgument);
130  return Args;
131  }
132 
133  // We avoid creating a virtual apply() method because
134  // it makes initializer lists harder to write.
135  private:
137  applyAsOutOfRange(ProgramStateRef State, const CallEvent &Call,
138  const FunctionSummaryTy &Summary) const;
140  applyAsWithinRange(ProgramStateRef State, const CallEvent &Call,
141  const FunctionSummaryTy &Summary) const;
143  applyAsComparesToArgument(ProgramStateRef State, const CallEvent &Call,
144  const FunctionSummaryTy &Summary) const;
145 
146  public:
147  ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
148  const FunctionSummaryTy &Summary) const {
149  switch (Kind) {
150  case OutOfRange:
151  return applyAsOutOfRange(State, Call, Summary);
152  case WithinRange:
153  return applyAsWithinRange(State, Call, Summary);
154  case ComparesToArgument:
155  return applyAsComparesToArgument(State, Call, Summary);
156  }
157  llvm_unreachable("Unknown ValueRange kind!");
158  }
159  };
160 
161  /// The complete list of ranges that defines a single branch.
162  typedef std::vector<ValueRange> ValueRangeSet;
163 
164  /// Includes information about function prototype (which is necessary to
165  /// ensure we're modeling the right function and casting values properly),
166  /// approach to invalidation, and a list of branches - essentially, a list
167  /// of list of ranges - essentially, a list of lists of lists of segments.
168  struct FunctionSummaryTy {
169  const std::vector<QualType> ArgTypes;
170  const QualType RetType;
171  const InvalidationKindTy InvalidationKind;
172  const std::vector<ValueRangeSet> Ranges;
173 
174  private:
175  static void assertTypeSuitableForSummary(QualType T) {
176  assert(!T->isVoidType() &&
177  "We should have had no significant void types in the spec");
178  assert(T.isCanonical() &&
179  "We should only have canonical types in the spec");
180  // FIXME: lift this assert (but not the ones above!)
181  assert(T->isIntegralOrEnumerationType() &&
182  "We only support integral ranges in the spec");
183  }
184 
185  public:
186  QualType getArgType(ArgNoTy ArgNo) const {
187  QualType T = (ArgNo == Ret) ? RetType : ArgTypes[ArgNo];
188  assertTypeSuitableForSummary(T);
189  return T;
190  }
191 
192  /// Try our best to figure out if the call expression is the call of
193  /// *the* library function to which this specification applies.
194  bool matchesCall(const CallExpr *CE) const;
195  };
196 
197  // The same function (as in, function identifier) may have different
198  // summaries assigned to it, with different argument and return value types.
199  // We call these "variants" of the function. This can be useful for handling
200  // C++ function overloads, and also it can be used when the same function
201  // may have different definitions on different platforms.
202  typedef std::vector<FunctionSummaryTy> FunctionVariantsTy;
203 
204  // The map of all functions supported by the checker. It is initialized
205  // lazily, and it doesn't change after initialization.
206  typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy;
207  mutable FunctionSummaryMapTy FunctionSummaryMap;
208 
209  // Auxiliary functions to support ArgNoTy within all structures
210  // in a unified manner.
211  static QualType getArgType(const FunctionSummaryTy &Summary, ArgNoTy ArgNo) {
212  return Summary.getArgType(ArgNo);
213  }
214  static QualType getArgType(const CallEvent &Call, ArgNoTy ArgNo) {
215  return ArgNo == Ret ? Call.getResultType().getCanonicalType()
216  : Call.getArgExpr(ArgNo)->getType().getCanonicalType();
217  }
218  static QualType getArgType(const CallExpr *CE, ArgNoTy ArgNo) {
219  return ArgNo == Ret ? CE->getType().getCanonicalType()
220  : CE->getArg(ArgNo)->getType().getCanonicalType();
221  }
222  static SVal getArgSVal(const CallEvent &Call, ArgNoTy ArgNo) {
223  return ArgNo == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgNo);
224  }
225 
226 public:
227  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
228  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
229 
230 private:
231  Optional<FunctionSummaryTy> findFunctionSummary(const FunctionDecl *FD,
232  const CallExpr *CE,
233  CheckerContext &C) const;
234 
235  void initFunctionSummaries(BasicValueFactory &BVF) const;
236 };
237 } // end of anonymous namespace
238 
239 ProgramStateRef StdLibraryFunctionsChecker::ValueRange::applyAsOutOfRange(
240  ProgramStateRef State, const CallEvent &Call,
241  const FunctionSummaryTy &Summary) const {
242 
243  ProgramStateManager &Mgr = State->getStateManager();
244  SValBuilder &SVB = Mgr.getSValBuilder();
247  QualType T = getArgType(Summary, getArgNo());
248  SVal V = getArgSVal(Call, getArgNo());
249 
250  if (auto N = V.getAs<NonLoc>()) {
251  const IntRangeVectorTy &R = getRanges();
252  size_t E = R.size();
253  for (size_t I = 0; I != E; ++I) {
254  const llvm::APSInt &Min = BVF.getValue(R[I].first, T);
255  const llvm::APSInt &Max = BVF.getValue(R[I].second, T);
256  assert(Min <= Max);
257  State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
258  if (!State)
259  break;
260  }
261  }
262 
263  return State;
264 }
265 
267 StdLibraryFunctionsChecker::ValueRange::applyAsWithinRange(
268  ProgramStateRef State, const CallEvent &Call,
269  const FunctionSummaryTy &Summary) const {
270 
271  ProgramStateManager &Mgr = State->getStateManager();
272  SValBuilder &SVB = Mgr.getSValBuilder();
275  QualType T = getArgType(Summary, getArgNo());
276  SVal V = getArgSVal(Call, getArgNo());
277 
278  // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R".
279  // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary,
280  // and then cut away all holes in R one by one.
281  if (auto N = V.getAs<NonLoc>()) {
282  const IntRangeVectorTy &R = getRanges();
283  size_t E = R.size();
284 
285  const llvm::APSInt &MinusInf = BVF.getMinValue(T);
286  const llvm::APSInt &PlusInf = BVF.getMaxValue(T);
287 
288  const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T);
289  if (Left != PlusInf) {
290  assert(MinusInf <= Left);
291  State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false);
292  if (!State)
293  return nullptr;
294  }
295 
296  const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T);
297  if (Right != MinusInf) {
298  assert(Right <= PlusInf);
299  State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false);
300  if (!State)
301  return nullptr;
302  }
303 
304  for (size_t I = 1; I != E; ++I) {
305  const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T);
306  const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T);
307  assert(Min <= Max);
308  State = CM.assumeInclusiveRange(State, *N, Min, Max, false);
309  if (!State)
310  return nullptr;
311  }
312  }
313 
314  return State;
315 }
316 
318 StdLibraryFunctionsChecker::ValueRange::applyAsComparesToArgument(
319  ProgramStateRef State, const CallEvent &Call,
320  const FunctionSummaryTy &Summary) const {
321 
322  ProgramStateManager &Mgr = State->getStateManager();
323  SValBuilder &SVB = Mgr.getSValBuilder();
324  QualType CondT = SVB.getConditionType();
325  QualType T = getArgType(Summary, getArgNo());
326  SVal V = getArgSVal(Call, getArgNo());
327 
329  ArgNoTy OtherArg = getOtherArgNo();
330  SVal OtherV = getArgSVal(Call, OtherArg);
331  QualType OtherT = getArgType(Call, OtherArg);
332  // Note: we avoid integral promotion for comparison.
333  OtherV = SVB.evalCast(OtherV, T, OtherT);
334  if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT)
336  State = State->assume(*CompV, true);
337  return State;
338 }
339 
340 void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call,
341  CheckerContext &C) const {
342  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
343  if (!FD)
344  return;
345 
346  const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr());
347  if (!CE)
348  return;
349 
350  Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
351  if (!FoundSummary)
352  return;
353 
354  // Now apply ranges.
355  const FunctionSummaryTy &Summary = *FoundSummary;
356  ProgramStateRef State = C.getState();
357 
358  for (const auto &VRS: Summary.Ranges) {
359  ProgramStateRef NewState = State;
360  for (const auto &VR: VRS) {
361  NewState = VR.apply(NewState, Call, Summary);
362  if (!NewState)
363  break;
364  }
365 
366  if (NewState && NewState != State)
367  C.addTransition(NewState);
368  }
369 }
370 
371 bool StdLibraryFunctionsChecker::evalCall(const CallExpr *CE,
372  CheckerContext &C) const {
373  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl());
374  if (!FD)
375  return false;
376 
377  Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C);
378  if (!FoundSummary)
379  return false;
380 
381  const FunctionSummaryTy &Summary = *FoundSummary;
382  switch (Summary.InvalidationKind) {
383  case EvalCallAsPure: {
384  ProgramStateRef State = C.getState();
385  const LocationContext *LC = C.getLocationContext();
387  CE, LC, CE->getType().getCanonicalType(), C.blockCount());
388  State = State->BindExpr(CE, LC, V);
389  C.addTransition(State);
390  return true;
391  }
392  case NoEvalCall:
393  // Summary tells us to avoid performing eval::Call. The function is possibly
394  // evaluated by another checker, or evaluated conservatively.
395  return false;
396  }
397  llvm_unreachable("Unknown invalidation kind!");
398 }
399 
400 bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall(
401  const CallExpr *CE) const {
402  // Check number of arguments:
403  if (CE->getNumArgs() != ArgTypes.size())
404  return false;
405 
406  // Check return type if relevant:
407  if (!RetType.isNull() && RetType != CE->getType().getCanonicalType())
408  return false;
409 
410  // Check argument types when relevant:
411  for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) {
412  QualType FormalT = ArgTypes[I];
413  // Null type marks irrelevant arguments.
414  if (FormalT.isNull())
415  continue;
416 
417  assertTypeSuitableForSummary(FormalT);
418 
419  QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I);
420  assert(ActualT.isCanonical());
421  if (ActualT != FormalT)
422  return false;
423  }
424 
425  return true;
426 }
427 
429 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD,
430  const CallExpr *CE,
431  CheckerContext &C) const {
432  // Note: we cannot always obtain FD from CE
433  // (eg. virtual call, or call by pointer).
434  assert(CE);
435 
436  if (!FD)
437  return None;
438 
439  SValBuilder &SVB = C.getSValBuilder();
441  initFunctionSummaries(BVF);
442 
443  IdentifierInfo *II = FD->getIdentifier();
444  if (!II)
445  return None;
446  StringRef Name = II->getName();
447  if (Name.empty() || !C.isCLibraryFunction(FD, Name))
448  return None;
449 
450  auto FSMI = FunctionSummaryMap.find(Name);
451  if (FSMI == FunctionSummaryMap.end())
452  return None;
453 
454  // Verify that function signature matches the spec in advance.
455  // Otherwise we might be modeling the wrong function.
456  // Strict checking is important because we will be conducting
457  // very integral-type-sensitive operations on arguments and
458  // return values.
459  const FunctionVariantsTy &SpecVariants = FSMI->second;
460  for (const FunctionSummaryTy &Spec : SpecVariants)
461  if (Spec.matchesCall(CE))
462  return Spec;
463 
464  return None;
465 }
466 
467 void StdLibraryFunctionsChecker::initFunctionSummaries(
468  BasicValueFactory &BVF) const {
469  if (!FunctionSummaryMap.empty())
470  return;
471 
472  ASTContext &ACtx = BVF.getContext();
473 
474  // These types are useful for writing specifications quickly,
475  // New specifications should probably introduce more types.
476  // Some types are hard to obtain from the AST, eg. "ssize_t".
477  // In such cases it should be possible to provide multiple variants
478  // of function summary for common cases (eg. ssize_t could be int or long
479  // or long long, so three summary variants would be enough).
480  // Of course, function variants are also useful for C++ overloads.
481  QualType Irrelevant; // A placeholder, whenever we do not care about the type.
482  QualType IntTy = ACtx.IntTy;
483  QualType LongTy = ACtx.LongTy;
484  QualType LongLongTy = ACtx.LongLongTy;
485  QualType SizeTy = ACtx.getSizeType();
486 
487  RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
488  RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
489  RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
490 
491  // We are finally ready to define specifications for all supported functions.
492  //
493  // The signature needs to have the correct number of arguments.
494  // However, we insert `Irrelevant' when the type is insignificant.
495  //
496  // Argument ranges should always cover all variants. If return value
497  // is completely unknown, omit it from the respective range set.
498  //
499  // All types in the spec need to be canonical.
500  //
501  // Every item in the list of range sets represents a particular
502  // execution path the analyzer would need to explore once
503  // the call is modeled - a new program state is constructed
504  // for every range set, and each range line in the range set
505  // corresponds to a specific constraint within this state.
506  //
507  // Upon comparing to another argument, the other argument is casted
508  // to the current argument's type. This avoids proper promotion but
509  // seems useful. For example, read() receives size_t argument,
510  // and its return value, which is of type ssize_t, cannot be greater
511  // than this argument. If we made a promotion, and the size argument
512  // is equal to, say, 10, then we'd impose a range of [0, 10] on the
513  // return value, however the correct range is [-1, 10].
514  //
515  // Please update the list of functions in the header after editing!
516  //
517  // The format is as follows:
518  //
519  //{ "function name",
520  // { spec:
521  // { argument types list, ... },
522  // return type, purity, { range set list:
523  // { range list:
524  // { argument index, within or out of, {{from, to}, ...} },
525  // { argument index, compares to argument, {{how, which}} },
526  // ...
527  // }
528  // }
529  // }
530  //}
531 
532 #define SUMMARY_WITH_VARIANTS(identifier) {#identifier, {
533 #define END_SUMMARY_WITH_VARIANTS }},
534 #define VARIANT(argument_types, return_type, invalidation_approach) \
535  { argument_types, return_type, invalidation_approach, {
536 #define END_VARIANT } },
537 #define SUMMARY(identifier, argument_types, return_type, \
538  invalidation_approach) \
539  { #identifier, { { argument_types, return_type, invalidation_approach, {
540 #define END_SUMMARY } } } },
541 #define ARGUMENT_TYPES(...) { __VA_ARGS__ }
542 #define RETURN_TYPE(x) x
543 #define INVALIDATION_APPROACH(x) x
544 #define CASE {
545 #define END_CASE },
546 #define ARGUMENT_CONDITION(argument_number, condition_kind) \
547  { argument_number, condition_kind, {
548 #define END_ARGUMENT_CONDITION }},
549 #define RETURN_VALUE_CONDITION(condition_kind) \
550  { Ret, condition_kind, {
551 #define END_RETURN_VALUE_CONDITION }},
552 #define ARG_NO(x) x##U
553 #define RANGE(x, y) { x, y },
554 #define SINGLE_VALUE(x) RANGE(x, x)
555 #define IS_LESS_THAN(arg) { BO_LE, arg }
556 
557  FunctionSummaryMap = {
558  // The isascii() family of functions.
559  SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
560  INVALIDATION_APPROACH(EvalCallAsPure))
561  CASE // Boils down to isupper() or islower() or isdigit()
562  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
563  RANGE('0', '9')
564  RANGE('A', 'Z')
565  RANGE('a', 'z')
567  RETURN_VALUE_CONDITION(OutOfRange)
568  SINGLE_VALUE(0)
570  END_CASE
571  CASE // The locale-specific range.
572  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
573  RANGE(128, 255)
575  // No post-condition. We are completely unaware of
576  // locale-specific return values.
577  END_CASE
578  CASE
579  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
580  RANGE('0', '9')
581  RANGE('A', 'Z')
582  RANGE('a', 'z')
583  RANGE(128, 255)
585  RETURN_VALUE_CONDITION(WithinRange)
586  SINGLE_VALUE(0)
588  END_CASE
590  SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
591  INVALIDATION_APPROACH(EvalCallAsPure))
592  CASE // isupper() or islower(). Note that 'Z' is less than 'a'.
593  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
594  RANGE('A', 'Z')
595  RANGE('a', 'z')
597  RETURN_VALUE_CONDITION(OutOfRange)
598  SINGLE_VALUE(0)
600  END_CASE
601  CASE // The locale-specific range.
602  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
603  RANGE(128, 255)
605  END_CASE
606  CASE // Other.
607  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
608  RANGE('A', 'Z')
609  RANGE('a', 'z')
610  RANGE(128, 255)
612  RETURN_VALUE_CONDITION(WithinRange)
613  SINGLE_VALUE(0)
615  END_CASE
617  SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
618  INVALIDATION_APPROACH(EvalCallAsPure))
619  CASE // Is ASCII.
620  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
621  RANGE(0, 127)
623  RETURN_VALUE_CONDITION(OutOfRange)
624  SINGLE_VALUE(0)
626  END_CASE
627  CASE
628  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
629  RANGE(0, 127)
631  RETURN_VALUE_CONDITION(WithinRange)
632  SINGLE_VALUE(0)
634  END_CASE
636  SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
637  INVALIDATION_APPROACH(EvalCallAsPure))
638  CASE
639  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
640  SINGLE_VALUE('\t')
641  SINGLE_VALUE(' ')
643  RETURN_VALUE_CONDITION(OutOfRange)
644  SINGLE_VALUE(0)
646  END_CASE
647  CASE
648  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
649  SINGLE_VALUE('\t')
650  SINGLE_VALUE(' ')
652  RETURN_VALUE_CONDITION(WithinRange)
653  SINGLE_VALUE(0)
655  END_CASE
657  SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
658  INVALIDATION_APPROACH(EvalCallAsPure))
659  CASE // 0..31 or 127
660  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
661  RANGE(0, 32)
662  SINGLE_VALUE(127)
664  RETURN_VALUE_CONDITION(OutOfRange)
665  SINGLE_VALUE(0)
667  END_CASE
668  CASE
669  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
670  RANGE(0, 32)
671  SINGLE_VALUE(127)
673  RETURN_VALUE_CONDITION(WithinRange)
674  SINGLE_VALUE(0)
676  END_CASE
678  SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
679  INVALIDATION_APPROACH(EvalCallAsPure))
680  CASE // Is a digit.
681  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
682  RANGE('0', '9')
684  RETURN_VALUE_CONDITION(OutOfRange)
685  SINGLE_VALUE(0)
687  END_CASE
688  CASE
689  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
690  RANGE('0', '9')
692  RETURN_VALUE_CONDITION(WithinRange)
693  SINGLE_VALUE(0)
695  END_CASE
697  SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
698  INVALIDATION_APPROACH(EvalCallAsPure))
699  CASE
700  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
701  RANGE(33, 126)
703  RETURN_VALUE_CONDITION(OutOfRange)
704  SINGLE_VALUE(0)
706  END_CASE
707  CASE
708  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
709  RANGE(33, 126)
711  RETURN_VALUE_CONDITION(WithinRange)
712  SINGLE_VALUE(0)
714  END_CASE
716  SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
717  INVALIDATION_APPROACH(EvalCallAsPure))
718  CASE // Is certainly lowercase.
719  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
720  RANGE('a', 'z')
722  RETURN_VALUE_CONDITION(OutOfRange)
723  SINGLE_VALUE(0)
725  END_CASE
726  CASE // Is ascii but not lowercase.
727  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
728  RANGE(0, 127)
730  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
731  RANGE('a', 'z')
733  RETURN_VALUE_CONDITION(WithinRange)
734  SINGLE_VALUE(0)
736  END_CASE
737  CASE // The locale-specific range.
738  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
739  RANGE(128, 255)
741  END_CASE
742  CASE // Is not an unsigned char.
743  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
744  RANGE(0, 255)
746  RETURN_VALUE_CONDITION(WithinRange)
747  SINGLE_VALUE(0)
749  END_CASE
751  SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
752  INVALIDATION_APPROACH(EvalCallAsPure))
753  CASE
754  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
755  RANGE(32, 126)
757  RETURN_VALUE_CONDITION(OutOfRange)
758  SINGLE_VALUE(0)
760  END_CASE
761  CASE
762  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
763  RANGE(32, 126)
765  RETURN_VALUE_CONDITION(WithinRange)
766  SINGLE_VALUE(0)
768  END_CASE
770  SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
771  INVALIDATION_APPROACH(EvalCallAsPure))
772  CASE
773  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
774  RANGE('!', '/')
775  RANGE(':', '@')
776  RANGE('[', '`')
777  RANGE('{', '~')
778  END_ARGUMENT_CONDITION
779  RETURN_VALUE_CONDITION(OutOfRange)
780  SINGLE_VALUE(0)
781  END_RETURN_VALUE_CONDITION
782  END_CASE
783  CASE
784  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
785  RANGE('!', '/')
786  RANGE(':', '@')
787  RANGE('[', '`')
788  RANGE('{', '~')
789  END_ARGUMENT_CONDITION
790  RETURN_VALUE_CONDITION(WithinRange)
791  SINGLE_VALUE(0)
792  END_RETURN_VALUE_CONDITION
793  END_CASE
794  END_SUMMARY
795  SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
796  INVALIDATION_APPROACH(EvalCallAsPure))
797  CASE // Space, '\f', '\n', '\r', '\t', '\v'.
798  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
799  RANGE(9, 13)
800  SINGLE_VALUE(' ')
801  END_ARGUMENT_CONDITION
802  RETURN_VALUE_CONDITION(OutOfRange)
803  SINGLE_VALUE(0)
804  END_RETURN_VALUE_CONDITION
805  END_CASE
806  CASE // The locale-specific range.
807  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
808  RANGE(128, 255)
809  END_ARGUMENT_CONDITION
810  END_CASE
811  CASE
812  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
813  RANGE(9, 13)
814  SINGLE_VALUE(' ')
815  RANGE(128, 255)
816  END_ARGUMENT_CONDITION
817  RETURN_VALUE_CONDITION(WithinRange)
818  SINGLE_VALUE(0)
819  END_RETURN_VALUE_CONDITION
820  END_CASE
821  END_SUMMARY
822  SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy),
823  INVALIDATION_APPROACH(EvalCallAsPure))
824  CASE // Is certainly uppercase.
825  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
826  RANGE('A', 'Z')
827  END_ARGUMENT_CONDITION
828  RETURN_VALUE_CONDITION(OutOfRange)
829  SINGLE_VALUE(0)
830  END_RETURN_VALUE_CONDITION
831  END_CASE
832  CASE // The locale-specific range.
833  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
834  RANGE(128, 255)
835  END_ARGUMENT_CONDITION
836  END_CASE
837  CASE // Other.
838  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
839  RANGE('A', 'Z') RANGE(128, 255)
840  END_ARGUMENT_CONDITION
841  RETURN_VALUE_CONDITION(WithinRange)
842  SINGLE_VALUE(0)
843  END_RETURN_VALUE_CONDITION
844  END_CASE
845  END_SUMMARY
846  SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy),
847  INVALIDATION_APPROACH(EvalCallAsPure))
848  CASE
849  ARGUMENT_CONDITION(ARG_NO(0), WithinRange)
850  RANGE('0', '9')
851  RANGE('A', 'F')
852  RANGE('a', 'f')
853  END_ARGUMENT_CONDITION
854  RETURN_VALUE_CONDITION(OutOfRange)
855  SINGLE_VALUE(0)
856  END_RETURN_VALUE_CONDITION
857  END_CASE
858  CASE
859  ARGUMENT_CONDITION(ARG_NO(0), OutOfRange)
860  RANGE('0', '9')
861  RANGE('A', 'F')
862  RANGE('a', 'f')
863  END_ARGUMENT_CONDITION
864  RETURN_VALUE_CONDITION(WithinRange)
865  SINGLE_VALUE(0)
866  END_RETURN_VALUE_CONDITION
867  END_CASE
868  END_SUMMARY
869 
870  // The getc() family of functions that returns either a char or an EOF.
871  SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
872  INVALIDATION_APPROACH(NoEvalCall))
873  CASE // FIXME: EOF is assumed to be defined as -1.
874  RETURN_VALUE_CONDITION(WithinRange)
875  RANGE(-1, 255)
876  END_RETURN_VALUE_CONDITION
877  END_CASE
878  END_SUMMARY
879  SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy),
880  INVALIDATION_APPROACH(NoEvalCall))
881  CASE // FIXME: EOF is assumed to be defined as -1.
882  RETURN_VALUE_CONDITION(WithinRange)
883  RANGE(-1, 255)
884  END_RETURN_VALUE_CONDITION
885  END_CASE
886  END_SUMMARY
887  SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy),
888  INVALIDATION_APPROACH(NoEvalCall))
889  CASE // FIXME: EOF is assumed to be defined as -1.
890  RETURN_VALUE_CONDITION(WithinRange)
891  RANGE(-1, 255)
892  END_RETURN_VALUE_CONDITION
893  END_CASE
894  END_SUMMARY
895 
896  // read()-like functions that never return more than buffer size.
897  // We are not sure how ssize_t is defined on every platform, so we provide
898  // three variants that should cover common cases.
899  SUMMARY_WITH_VARIANTS(read)
900  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
901  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
902  CASE
903  RETURN_VALUE_CONDITION(ComparesToArgument)
904  IS_LESS_THAN(ARG_NO(2))
905  END_RETURN_VALUE_CONDITION
906  RETURN_VALUE_CONDITION(WithinRange)
907  RANGE(-1, IntMax)
908  END_RETURN_VALUE_CONDITION
909  END_CASE
910  END_VARIANT
911  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
912  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
913  CASE
914  RETURN_VALUE_CONDITION(ComparesToArgument)
915  IS_LESS_THAN(ARG_NO(2))
916  END_RETURN_VALUE_CONDITION
917  RETURN_VALUE_CONDITION(WithinRange)
918  RANGE(-1, LongMax)
919  END_RETURN_VALUE_CONDITION
920  END_CASE
921  END_VARIANT
922  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
923  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
924  CASE
925  RETURN_VALUE_CONDITION(ComparesToArgument)
926  IS_LESS_THAN(ARG_NO(2))
927  END_RETURN_VALUE_CONDITION
928  RETURN_VALUE_CONDITION(WithinRange)
929  RANGE(-1, LongLongMax)
930  END_RETURN_VALUE_CONDITION
931  END_CASE
932  END_VARIANT
933  END_SUMMARY_WITH_VARIANTS
934  SUMMARY_WITH_VARIANTS(write)
935  // Again, due to elusive nature of ssize_t, we have duplicate
936  // our summaries to cover different variants.
937  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
938  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
939  CASE
940  RETURN_VALUE_CONDITION(ComparesToArgument)
941  IS_LESS_THAN(ARG_NO(2))
942  END_RETURN_VALUE_CONDITION
943  RETURN_VALUE_CONDITION(WithinRange)
944  RANGE(-1, IntMax)
945  END_RETURN_VALUE_CONDITION
946  END_CASE
947  END_VARIANT
948  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
949  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
950  CASE
951  RETURN_VALUE_CONDITION(ComparesToArgument)
952  IS_LESS_THAN(ARG_NO(2))
953  END_RETURN_VALUE_CONDITION
954  RETURN_VALUE_CONDITION(WithinRange)
955  RANGE(-1, LongMax)
956  END_RETURN_VALUE_CONDITION
957  END_CASE
958  END_VARIANT
959  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
960  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
961  CASE
962  RETURN_VALUE_CONDITION(ComparesToArgument)
963  IS_LESS_THAN(ARG_NO(2))
964  END_RETURN_VALUE_CONDITION
965  RETURN_VALUE_CONDITION(WithinRange)
966  RANGE(-1, LongLongMax)
967  END_RETURN_VALUE_CONDITION
968  END_CASE
969  END_VARIANT
970  END_SUMMARY_WITH_VARIANTS
971  SUMMARY(fread,
972  ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
973  RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
974  CASE
975  RETURN_VALUE_CONDITION(ComparesToArgument)
976  IS_LESS_THAN(ARG_NO(2))
977  END_RETURN_VALUE_CONDITION
978  END_CASE
979  END_SUMMARY
980  SUMMARY(fwrite,
981  ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
982  RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
983  CASE
984  RETURN_VALUE_CONDITION(ComparesToArgument)
985  IS_LESS_THAN(ARG_NO(2))
986  END_RETURN_VALUE_CONDITION
987  END_CASE
988  END_SUMMARY
989 
990  // getline()-like functions either fail or read at least the delimiter.
991  SUMMARY_WITH_VARIANTS(getline)
992  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
993  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
994  CASE
995  RETURN_VALUE_CONDITION(WithinRange)
996  SINGLE_VALUE(-1)
997  RANGE(1, IntMax)
998  END_RETURN_VALUE_CONDITION
999  END_CASE
1000  END_VARIANT
1001  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1002  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1003  CASE
1004  RETURN_VALUE_CONDITION(WithinRange)
1005  SINGLE_VALUE(-1)
1006  RANGE(1, LongMax)
1007  END_RETURN_VALUE_CONDITION
1008  END_CASE
1009  END_VARIANT
1010  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
1011  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1012  CASE
1013  RETURN_VALUE_CONDITION(WithinRange)
1014  SINGLE_VALUE(-1)
1015  RANGE(1, LongLongMax)
1016  END_RETURN_VALUE_CONDITION
1017  END_CASE
1018  END_VARIANT
1019  END_SUMMARY_WITH_VARIANTS
1020  SUMMARY_WITH_VARIANTS(getdelim)
1021  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1022  RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
1023  CASE
1024  RETURN_VALUE_CONDITION(WithinRange)
1025  SINGLE_VALUE(-1)
1026  RANGE(1, IntMax)
1027  END_RETURN_VALUE_CONDITION
1028  END_CASE
1029  END_VARIANT
1030  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1031  RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
1032  CASE
1033  RETURN_VALUE_CONDITION(WithinRange)
1034  SINGLE_VALUE(-1)
1035  RANGE(1, LongMax)
1036  END_RETURN_VALUE_CONDITION
1037  END_CASE
1038  END_VARIANT
1039  VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
1040  RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
1041  CASE
1042  RETURN_VALUE_CONDITION(WithinRange)
1043  SINGLE_VALUE(-1)
1044  RANGE(1, LongLongMax)
1045  END_RETURN_VALUE_CONDITION
1046  END_CASE
1047  END_VARIANT
1048  END_SUMMARY_WITH_VARIANTS
1049  };
1050 }
1051 
1052 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) {
1053  // If this checker grows large enough to support C++, Objective-C, or other
1054  // standard libraries, we could use multiple register...Checker() functions,
1055  // which would register various checkers with the help of the same Checker
1056  // class, turning on different function summaries.
1057  mgr.registerChecker<StdLibraryFunctionsChecker>();
1058 }
CanQualType LongLongTy
Definition: ASTContext.h:1004
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1698
A (possibly-)qualified type.
Definition: Type.h:653
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition: Expr.h:2278
#define END_CASE
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Definition: Expr.h:2266
#define RETURN_TYPE(x)
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
CanQualType LongTy
Definition: ASTContext.h:1004
SVal evalCast(SVal val, QualType castTy, QualType originalType)
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
Definition: CallEvent.h:225
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:265
#define END_SUMMARY
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:149
LineState State
virtual const Expr * getArgExpr(unsigned Index) const
Returns the expression associated with a given argument.
Definition: CallEvent.h:275
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:6221
BinaryOperatorKind
#define END_RETURN_VALUE_CONDITION
#define SUMMARY(identifier, argument_types, return_type, invalidation_approach)
SVal getReturnValue() const
Returns the return value of the call.
Definition: CallEvent.cpp:242
const FunctionProtoType * T
#define RETURN_VALUE_CONDITION(condition_kind)
#define ARG_NO(x)
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name=StringRef())
Returns true if the callee is an externally-visible function in the top-level namespace, such as malloc.
QualType getConditionType() const
Definition: SValBuilder.h:136
QualType getType() const
Definition: Expr.h:128
virtual const Decl * getDecl() const
Returns the declaration of the function or method that will be called.
Definition: CallEvent.h:205
SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type)
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:719
do v
Definition: arm_acle.h:78
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
Definition: SVals.h:100
virtual ProgramStateRef assumeInclusiveRange(ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, const llvm::APSInt &To, bool InBound)=0
bool isComparisonOp() const
Definition: Expr.h:3076
#define RANGE(x, y)
Kind
QualType getCanonicalType() const
Definition: Type.h:5759
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique &#39;name&#39;.
#define SINGLE_VALUE(x)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:63
#define ARGUMENT_CONDITION(argument_number, condition_kind)
#define ARGUMENT_TYPES(...)
bool isCanonical() const
Definition: Type.h:5764
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
Dataflow Directional Tag Classes.
BinaryOperator::Opcode getOpcode(const SymExpr *SE)
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:140
const llvm::APSInt & getMinValue(const llvm::APSInt &v)
Decl * getCalleeDecl()
Definition: Expr.cpp:1220
ConstraintManager & getConstraintManager()
Definition: ProgramState.h:530
BasicValueFactory & getBasicValueFactory()
Definition: SValBuilder.h:144
const ProgramStateRef & getState() const
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
QualType getResultType() const
Returns the result type, adjusted for references.
Definition: CallEvent.cpp:31
bool isVoidType() const
Definition: Type.h:6171
#define CASE
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2209
const llvm::APSInt & getMaxValue(const llvm::APSInt &v)
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:915
CanQualType IntTy
Definition: ASTContext.h:1004
#define INVALIDATION_APPROACH(x)
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
Definition: CallEvent.cpp:228
#define END_ARGUMENT_CONDITION
const LocationContext * getLocationContext() const
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.