StdLibraryFunctionsChecker.cpp 38 KB

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