StdLibraryFunctionsChecker.cpp 38 KB

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