StdLibraryFunctionsChecker.cpp 111 KB

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