1bba497fbSArtem Dergachev //=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===// 2bba497fbSArtem Dergachev // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bba497fbSArtem Dergachev // 7bba497fbSArtem Dergachev //===----------------------------------------------------------------------===// 8bba497fbSArtem Dergachev // 9bba497fbSArtem Dergachev // This checker improves modeling of a few simple library functions. 10bba497fbSArtem Dergachev // 11f5086b38SGabor Marton // This checker provides a specification format - `Summary' - and 12bba497fbSArtem Dergachev // contains descriptions of some library functions in this format. Each 13bba497fbSArtem Dergachev // specification contains a list of branches for splitting the program state 14bba497fbSArtem Dergachev // upon call, and range constraints on argument and return-value symbols that 15bba497fbSArtem Dergachev // are satisfied on each branch. This spec can be expanded to include more 16bba497fbSArtem Dergachev // items, like external effects of the function. 17bba497fbSArtem Dergachev // 18bba497fbSArtem Dergachev // The main difference between this approach and the body farms technique is 19bba497fbSArtem Dergachev // in more explicit control over how many branches are produced. For example, 20bba497fbSArtem Dergachev // consider standard C function `ispunct(int x)', which returns a non-zero value 21bba497fbSArtem Dergachev // iff `x' is a punctuation character, that is, when `x' is in range 22bba497fbSArtem Dergachev // ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~']. 23f5086b38SGabor Marton // `Summary' provides only two branches for this function. However, 24bba497fbSArtem Dergachev // any attempt to describe this range with if-statements in the body farm 25bba497fbSArtem Dergachev // would result in many more branches. Because each branch needs to be analyzed 26bba497fbSArtem Dergachev // independently, this significantly reduces performance. Additionally, 27bba497fbSArtem Dergachev // once we consider a branch on which `x' is in range, say, ['!', '/'], 28bba497fbSArtem Dergachev // we assume that such branch is an important separate path through the program, 29bba497fbSArtem Dergachev // which may lead to false positives because considering this particular path 30bba497fbSArtem Dergachev // was not consciously intended, and therefore it might have been unreachable. 31bba497fbSArtem Dergachev // 32f5086b38SGabor Marton // This checker uses eval::Call for modeling pure functions (functions without 33f5086b38SGabor Marton // side effets), for which their `Summary' is a precise model. This avoids 34f5086b38SGabor Marton // unnecessary invalidation passes. Conflicts with other checkers are unlikely 35f5086b38SGabor Marton // because if the function has no other effects, other checkers would probably 36f5086b38SGabor Marton // never want to improve upon the modeling done by this checker. 37bba497fbSArtem Dergachev // 38f5086b38SGabor Marton // Non-pure functions, for which only partial improvement over the default 39bba497fbSArtem Dergachev // behavior is expected, are modeled via check::PostCall, non-intrusively. 40bba497fbSArtem Dergachev // 41bba497fbSArtem Dergachev // The following standard C functions are currently supported: 42bba497fbSArtem Dergachev // 4325bbe234SZurab Tsinadze // fgetc getline isdigit isupper toascii 44bba497fbSArtem Dergachev // fread isalnum isgraph isxdigit 45bba497fbSArtem Dergachev // fwrite isalpha islower read 46bba497fbSArtem Dergachev // getc isascii isprint write 4725bbe234SZurab Tsinadze // getchar isblank ispunct toupper 4825bbe234SZurab Tsinadze // getdelim iscntrl isspace tolower 49bba497fbSArtem Dergachev // 50bba497fbSArtem Dergachev //===----------------------------------------------------------------------===// 51bba497fbSArtem Dergachev 5276a21502SKristof Umann #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 5394061df6SGabor Marton #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 54bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/Checker.h" 55bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/CheckerManager.h" 56bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 57bba497fbSArtem Dergachev #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 58536456a7SGabor Marton #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" 599b3df78bSCharusso #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h" 60a7cb951fSGabor Marton #include "llvm/ADT/SmallString.h" 61a7cb951fSGabor Marton #include "llvm/ADT/StringExtras.h" 62a7cb951fSGabor Marton 63a7cb951fSGabor Marton #include <string> 64bba497fbSArtem Dergachev 65bba497fbSArtem Dergachev using namespace clang; 66bba497fbSArtem Dergachev using namespace clang::ento; 67bba497fbSArtem Dergachev 68bba497fbSArtem Dergachev namespace { 6994061df6SGabor Marton class StdLibraryFunctionsChecker 7094061df6SGabor Marton : public Checker<check::PreCall, check::PostCall, eval::Call> { 7116506d78SGabor Marton 7216506d78SGabor Marton class Summary; 73bba497fbSArtem Dergachev 74bba497fbSArtem Dergachev /// Specify how much the analyzer engine should entrust modeling this function 75bba497fbSArtem Dergachev /// to us. If he doesn't, he performs additional invalidations. 76f5086b38SGabor Marton enum InvalidationKind { NoEvalCall, EvalCallAsPure }; 77bba497fbSArtem Dergachev 7847fec16cSArtem Dergachev // The universal integral type to use in value range descriptions. 7947fec16cSArtem Dergachev // Unsigned to make sure overflows are well-defined. 80f5086b38SGabor Marton typedef uint64_t RangeInt; 8147fec16cSArtem Dergachev 82bba497fbSArtem Dergachev /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is 83bba497fbSArtem Dergachev /// a non-negative integer, which less than 5 and not equal to 2. For 84bba497fbSArtem Dergachev /// `ComparesToArgument', holds information about how exactly to compare to 85bba497fbSArtem Dergachev /// the argument. 86f5086b38SGabor Marton typedef std::vector<std::pair<RangeInt, RangeInt>> IntRangeVector; 87bba497fbSArtem Dergachev 88bba497fbSArtem Dergachev /// A reference to an argument or return value by its number. 89bba497fbSArtem Dergachev /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but 90bba497fbSArtem Dergachev /// obviously uint32_t should be enough for all practical purposes. 91f5086b38SGabor Marton typedef uint32_t ArgNo; 92c6b8484eSGabor Marton static const ArgNo Ret; 93bba497fbSArtem Dergachev 94a7cb951fSGabor Marton /// Returns the string representation of an argument index. 95a7cb951fSGabor Marton /// E.g.: (1) -> '1st arg', (2) - > '2nd arg' 96a7cb951fSGabor Marton static SmallString<8> getArgDesc(ArgNo); 97a7cb951fSGabor Marton 9894061df6SGabor Marton class ValueConstraint; 9994061df6SGabor Marton 10094061df6SGabor Marton // Pointer to the ValueConstraint. We need a copyable, polymorphic and 10194061df6SGabor Marton // default initialize able type (vector needs that). A raw pointer was good, 10294061df6SGabor Marton // however, we cannot default initialize that. unique_ptr makes the Summary 10394061df6SGabor Marton // class non-copyable, therefore not an option. Releasing the copyability 10494061df6SGabor Marton // requirement would render the initialization of the Summary map infeasible. 10594061df6SGabor Marton using ValueConstraintPtr = std::shared_ptr<ValueConstraint>; 10694061df6SGabor Marton 107c6b8484eSGabor Marton /// Polymorphic base class that represents a constraint on a given argument 108c6b8484eSGabor Marton /// (or return value) of a function. Derived classes implement different kind 109c6b8484eSGabor Marton /// of constraints, e.g range constraints or correlation between two 110c6b8484eSGabor Marton /// arguments. 111c6b8484eSGabor Marton class ValueConstraint { 112c6b8484eSGabor Marton public: 113c6b8484eSGabor Marton ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {} 114c6b8484eSGabor Marton virtual ~ValueConstraint() {} 115c6b8484eSGabor Marton /// Apply the effects of the constraint on the given program state. If null 116c6b8484eSGabor Marton /// is returned then the constraint is not feasible. 117c6b8484eSGabor Marton virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 118bd03ef19SGabor Marton const Summary &Summary, 119bd03ef19SGabor Marton CheckerContext &C) const = 0; 12094061df6SGabor Marton virtual ValueConstraintPtr negate() const { 12194061df6SGabor Marton llvm_unreachable("Not implemented"); 12294061df6SGabor Marton }; 12316506d78SGabor Marton 12416506d78SGabor Marton // Check whether the constraint is malformed or not. It is malformed if the 12516506d78SGabor Marton // specified argument has a mismatch with the given FunctionDecl (e.g. the 12616506d78SGabor Marton // arg number is out-of-range of the function's argument list). 12716506d78SGabor Marton bool checkValidity(const FunctionDecl *FD) const { 12816506d78SGabor Marton const bool ValidArg = ArgN == Ret || ArgN < FD->getNumParams(); 12916506d78SGabor Marton assert(ValidArg && "Arg out of range!"); 13016506d78SGabor Marton if (!ValidArg) 13116506d78SGabor Marton return false; 13216506d78SGabor Marton // Subclasses may further refine the validation. 13316506d78SGabor Marton return checkSpecificValidity(FD); 13416506d78SGabor Marton } 135c6b8484eSGabor Marton ArgNo getArgNo() const { return ArgN; } 136c6b8484eSGabor Marton 1374b99f9c7SGabor Marton // Return those arguments that should be tracked when we report a bug. By 1384b99f9c7SGabor Marton // default it is the argument that is constrained, however, in some special 1394b99f9c7SGabor Marton // cases we need to track other arguments as well. E.g. a buffer size might 1404b99f9c7SGabor Marton // be encoded in another argument. 1414b99f9c7SGabor Marton virtual std::vector<ArgNo> getArgsToTrack() const { return {ArgN}; } 1424b99f9c7SGabor Marton 143a97648b9SGabor Marton virtual StringRef getName() const = 0; 144a97648b9SGabor Marton 145a7cb951fSGabor Marton // Give a description that explains the constraint to the user. Used when 146a7cb951fSGabor Marton // the bug is reported. 147a7cb951fSGabor Marton virtual std::string describe(ProgramStateRef State, 148a7cb951fSGabor Marton const Summary &Summary) const { 149a7cb951fSGabor Marton // There are some descendant classes that are not used as argument 150a7cb951fSGabor Marton // constraints, e.g. ComparisonConstraint. In that case we can safely 151a7cb951fSGabor Marton // ignore the implementation of this function. 152a7cb951fSGabor Marton llvm_unreachable("Not implemented"); 153a7cb951fSGabor Marton } 154a7cb951fSGabor Marton 155c6b8484eSGabor Marton protected: 156c6b8484eSGabor Marton ArgNo ArgN; // Argument to which we apply the constraint. 15716506d78SGabor Marton 15816506d78SGabor Marton /// Do polymorphic sanity check on the constraint. 15916506d78SGabor Marton virtual bool checkSpecificValidity(const FunctionDecl *FD) const { 16016506d78SGabor Marton return true; 16116506d78SGabor Marton } 162c6b8484eSGabor Marton }; 163c6b8484eSGabor Marton 164c6b8484eSGabor Marton /// Given a range, should the argument stay inside or outside this range? 165c6b8484eSGabor Marton enum RangeKind { OutOfRange, WithinRange }; 166c6b8484eSGabor Marton 167a787a4edSGabor Marton /// Encapsulates a range on a single symbol. 168c6b8484eSGabor Marton class RangeConstraint : public ValueConstraint { 169a787a4edSGabor Marton RangeKind Kind; 170a787a4edSGabor Marton // A range is formed as a set of intervals (sub-ranges). 171a787a4edSGabor Marton // E.g. {['A', 'Z'], ['a', 'z']} 172a787a4edSGabor Marton // 173a787a4edSGabor Marton // The default constructed RangeConstraint has an empty range set, applying 174a787a4edSGabor Marton // such constraint does not involve any assumptions, thus the State remains 175a787a4edSGabor Marton // unchanged. This is meaningful, if the range is dependent on a looked up 176a787a4edSGabor Marton // type (e.g. [0, Socklen_tMax]). If the type is not found, then the range 177a787a4edSGabor Marton // is default initialized to be empty. 178a787a4edSGabor Marton IntRangeVector Ranges; 179bba497fbSArtem Dergachev 180bba497fbSArtem Dergachev public: 181a97648b9SGabor Marton StringRef getName() const override { return "Range"; } 182a787a4edSGabor Marton RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Ranges) 183a787a4edSGabor Marton : ValueConstraint(ArgN), Kind(Kind), Ranges(Ranges) {} 184bba497fbSArtem Dergachev 185a7cb951fSGabor Marton std::string describe(ProgramStateRef State, 186a7cb951fSGabor Marton const Summary &Summary) const override; 187a7cb951fSGabor Marton 188a787a4edSGabor Marton const IntRangeVector &getRanges() const { return Ranges; } 189bba497fbSArtem Dergachev 190bba497fbSArtem Dergachev private: 191f5086b38SGabor Marton ProgramStateRef applyAsOutOfRange(ProgramStateRef State, 192f5086b38SGabor Marton const CallEvent &Call, 193f5086b38SGabor Marton const Summary &Summary) const; 194f5086b38SGabor Marton ProgramStateRef applyAsWithinRange(ProgramStateRef State, 195f5086b38SGabor Marton const CallEvent &Call, 196f5086b38SGabor Marton const Summary &Summary) const; 19725bbe234SZurab Tsinadze 198bba497fbSArtem Dergachev public: 199bba497fbSArtem Dergachev ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 200bd03ef19SGabor Marton const Summary &Summary, 201bd03ef19SGabor Marton CheckerContext &C) const override { 202bba497fbSArtem Dergachev switch (Kind) { 203bba497fbSArtem Dergachev case OutOfRange: 204bba497fbSArtem Dergachev return applyAsOutOfRange(State, Call, Summary); 205bba497fbSArtem Dergachev case WithinRange: 206bba497fbSArtem Dergachev return applyAsWithinRange(State, Call, Summary); 207bba497fbSArtem Dergachev } 208c6b8484eSGabor Marton llvm_unreachable("Unknown range kind!"); 209bba497fbSArtem Dergachev } 21094061df6SGabor Marton 21194061df6SGabor Marton ValueConstraintPtr negate() const override { 21294061df6SGabor Marton RangeConstraint Tmp(*this); 21394061df6SGabor Marton switch (Kind) { 21494061df6SGabor Marton case OutOfRange: 21594061df6SGabor Marton Tmp.Kind = WithinRange; 21694061df6SGabor Marton break; 21794061df6SGabor Marton case WithinRange: 21894061df6SGabor Marton Tmp.Kind = OutOfRange; 21994061df6SGabor Marton break; 22094061df6SGabor Marton } 22194061df6SGabor Marton return std::make_shared<RangeConstraint>(Tmp); 22294061df6SGabor Marton } 22316506d78SGabor Marton 22416506d78SGabor Marton bool checkSpecificValidity(const FunctionDecl *FD) const override { 22516506d78SGabor Marton const bool ValidArg = 22616506d78SGabor Marton getArgType(FD, ArgN)->isIntegralType(FD->getASTContext()); 22716506d78SGabor Marton assert(ValidArg && 22816506d78SGabor Marton "This constraint should be applied on an integral type"); 22916506d78SGabor Marton return ValidArg; 23016506d78SGabor Marton } 231bba497fbSArtem Dergachev }; 232bba497fbSArtem Dergachev 233c6b8484eSGabor Marton class ComparisonConstraint : public ValueConstraint { 234c6b8484eSGabor Marton BinaryOperator::Opcode Opcode; 235c6b8484eSGabor Marton ArgNo OtherArgN; 236c6b8484eSGabor Marton 237c6b8484eSGabor Marton public: 238a97648b9SGabor Marton virtual StringRef getName() const override { return "Comparison"; }; 239c6b8484eSGabor Marton ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode, 240c6b8484eSGabor Marton ArgNo OtherArgN) 241c6b8484eSGabor Marton : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {} 242c6b8484eSGabor Marton ArgNo getOtherArgNo() const { return OtherArgN; } 243c6b8484eSGabor Marton BinaryOperator::Opcode getOpcode() const { return Opcode; } 244c6b8484eSGabor Marton ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 245bd03ef19SGabor Marton const Summary &Summary, 246bd03ef19SGabor Marton CheckerContext &C) const override; 247c6b8484eSGabor Marton }; 248c6b8484eSGabor Marton 249ededa65dSGabor Marton class NotNullConstraint : public ValueConstraint { 250ededa65dSGabor Marton using ValueConstraint::ValueConstraint; 251ededa65dSGabor Marton // This variable has a role when we negate the constraint. 252ededa65dSGabor Marton bool CannotBeNull = true; 253ededa65dSGabor Marton 254ededa65dSGabor Marton public: 255a7cb951fSGabor Marton std::string describe(ProgramStateRef State, 256a7cb951fSGabor Marton const Summary &Summary) const override; 257a97648b9SGabor Marton StringRef getName() const override { return "NonNull"; } 258ededa65dSGabor Marton ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 259bd03ef19SGabor Marton const Summary &Summary, 260bd03ef19SGabor Marton CheckerContext &C) const override { 261ededa65dSGabor Marton SVal V = getArgSVal(Call, getArgNo()); 262defd95efSVince Bridgers if (V.isUndef()) 263defd95efSVince Bridgers return State; 264defd95efSVince Bridgers 265ededa65dSGabor Marton DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>(); 266ededa65dSGabor Marton if (!L.getAs<Loc>()) 267ededa65dSGabor Marton return State; 268ededa65dSGabor Marton 269ededa65dSGabor Marton return State->assume(L, CannotBeNull); 270ededa65dSGabor Marton } 271ededa65dSGabor Marton 272ededa65dSGabor Marton ValueConstraintPtr negate() const override { 273ededa65dSGabor Marton NotNullConstraint Tmp(*this); 274ededa65dSGabor Marton Tmp.CannotBeNull = !this->CannotBeNull; 275ededa65dSGabor Marton return std::make_shared<NotNullConstraint>(Tmp); 276ededa65dSGabor Marton } 27716506d78SGabor Marton 27816506d78SGabor Marton bool checkSpecificValidity(const FunctionDecl *FD) const override { 27916506d78SGabor Marton const bool ValidArg = getArgType(FD, ArgN)->isPointerType(); 28016506d78SGabor Marton assert(ValidArg && 28116506d78SGabor Marton "This constraint should be applied only on a pointer type"); 28216506d78SGabor Marton return ValidArg; 28316506d78SGabor Marton } 284ededa65dSGabor Marton }; 285ededa65dSGabor Marton 286f0b9dbcfSGabor Marton // Represents a buffer argument with an additional size constraint. The 287f0b9dbcfSGabor Marton // constraint may be a concrete value, or a symbolic value in an argument. 288f0b9dbcfSGabor Marton // Example 1. Concrete value as the minimum buffer size. 289f0b9dbcfSGabor Marton // char *asctime_r(const struct tm *restrict tm, char *restrict buf); 290f0b9dbcfSGabor Marton // // `buf` size must be at least 26 bytes according the POSIX standard. 291f0b9dbcfSGabor Marton // Example 2. Argument as a buffer size. 292bd03ef19SGabor Marton // ctime_s(char *buffer, rsize_t bufsz, const time_t *time); 293f0b9dbcfSGabor Marton // Example 3. The size is computed as a multiplication of other args. 29441928c97SGabor Marton // size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 29541928c97SGabor Marton // // Here, ptr is the buffer, and its minimum size is `size * nmemb`. 296bd03ef19SGabor Marton class BufferSizeConstraint : public ValueConstraint { 297f0b9dbcfSGabor Marton // The concrete value which is the minimum size for the buffer. 298f0b9dbcfSGabor Marton llvm::Optional<llvm::APSInt> ConcreteSize; 299bd03ef19SGabor Marton // The argument which holds the size of the buffer. 300f0b9dbcfSGabor Marton llvm::Optional<ArgNo> SizeArgN; 30141928c97SGabor Marton // The argument which is a multiplier to size. This is set in case of 30241928c97SGabor Marton // `fread` like functions where the size is computed as a multiplication of 30341928c97SGabor Marton // two arguments. 30441928c97SGabor Marton llvm::Optional<ArgNo> SizeMultiplierArgN; 305bd03ef19SGabor Marton // The operator we use in apply. This is negated in negate(). 306bd03ef19SGabor Marton BinaryOperator::Opcode Op = BO_LE; 307bd03ef19SGabor Marton 308bd03ef19SGabor Marton public: 309a97648b9SGabor Marton StringRef getName() const override { return "BufferSize"; } 310f0b9dbcfSGabor Marton BufferSizeConstraint(ArgNo Buffer, llvm::APSInt BufMinSize) 311f0b9dbcfSGabor Marton : ValueConstraint(Buffer), ConcreteSize(BufMinSize) {} 312bd03ef19SGabor Marton BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize) 313bd03ef19SGabor Marton : ValueConstraint(Buffer), SizeArgN(BufSize) {} 31441928c97SGabor Marton BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier) 31541928c97SGabor Marton : ValueConstraint(Buffer), SizeArgN(BufSize), 31641928c97SGabor Marton SizeMultiplierArgN(BufSizeMultiplier) {} 31741928c97SGabor Marton 3184b99f9c7SGabor Marton std::vector<ArgNo> getArgsToTrack() const override { 3194b99f9c7SGabor Marton std::vector<ArgNo> Result{ArgN}; 3204b99f9c7SGabor Marton if (SizeArgN) 3214b99f9c7SGabor Marton Result.push_back(*SizeArgN); 3224b99f9c7SGabor Marton if (SizeMultiplierArgN) 3234b99f9c7SGabor Marton Result.push_back(*SizeMultiplierArgN); 3244b99f9c7SGabor Marton return Result; 3254b99f9c7SGabor Marton } 3264b99f9c7SGabor Marton 327a7cb951fSGabor Marton std::string describe(ProgramStateRef State, 328a7cb951fSGabor Marton const Summary &Summary) const override; 329a7cb951fSGabor Marton 330bd03ef19SGabor Marton ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 331bd03ef19SGabor Marton const Summary &Summary, 332bd03ef19SGabor Marton CheckerContext &C) const override { 33341928c97SGabor Marton SValBuilder &SvalBuilder = C.getSValBuilder(); 334bd03ef19SGabor Marton // The buffer argument. 335bd03ef19SGabor Marton SVal BufV = getArgSVal(Call, getArgNo()); 336f0b9dbcfSGabor Marton 337f0b9dbcfSGabor Marton // Get the size constraint. 338f0b9dbcfSGabor Marton const SVal SizeV = [this, &State, &Call, &Summary, &SvalBuilder]() { 339f0b9dbcfSGabor Marton if (ConcreteSize) { 340f0b9dbcfSGabor Marton return SVal(SvalBuilder.makeIntVal(*ConcreteSize)); 341a7cb951fSGabor Marton } 342a7cb951fSGabor Marton assert(SizeArgN && "The constraint must be either a concrete value or " 343a7cb951fSGabor Marton "encoded in an argument."); 344bd03ef19SGabor Marton // The size argument. 345f0b9dbcfSGabor Marton SVal SizeV = getArgSVal(Call, *SizeArgN); 34641928c97SGabor Marton // Multiply with another argument if given. 34741928c97SGabor Marton if (SizeMultiplierArgN) { 34841928c97SGabor Marton SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN); 34941928c97SGabor Marton SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV, 350f0b9dbcfSGabor Marton Summary.getArgType(*SizeArgN)); 35141928c97SGabor Marton } 352f0b9dbcfSGabor Marton return SizeV; 353f0b9dbcfSGabor Marton }(); 354f0b9dbcfSGabor Marton 355bd03ef19SGabor Marton // The dynamic size of the buffer argument, got from the analyzer engine. 3569b3df78bSCharusso SVal BufDynSize = getDynamicExtentWithOffset(State, BufV); 357bd03ef19SGabor Marton 358bd03ef19SGabor Marton SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize, 359bd03ef19SGabor Marton SvalBuilder.getContext().BoolTy); 360bd03ef19SGabor Marton if (auto F = Feasible.getAs<DefinedOrUnknownSVal>()) 361bd03ef19SGabor Marton return State->assume(*F, true); 362bd03ef19SGabor Marton 363bd03ef19SGabor Marton // We can get here only if the size argument or the dynamic size is 364bd03ef19SGabor Marton // undefined. But the dynamic size should never be undefined, only 365bd03ef19SGabor Marton // unknown. So, here, the size of the argument is undefined, i.e. we 366bd03ef19SGabor Marton // cannot apply the constraint. Actually, other checkers like 367bd03ef19SGabor Marton // CallAndMessage should catch this situation earlier, because we call a 368bd03ef19SGabor Marton // function with an uninitialized argument. 369bd03ef19SGabor Marton llvm_unreachable("Size argument or the dynamic size is Undefined"); 370bd03ef19SGabor Marton } 371bd03ef19SGabor Marton 372bd03ef19SGabor Marton ValueConstraintPtr negate() const override { 373bd03ef19SGabor Marton BufferSizeConstraint Tmp(*this); 374bd03ef19SGabor Marton Tmp.Op = BinaryOperator::negateComparisonOp(Op); 375bd03ef19SGabor Marton return std::make_shared<BufferSizeConstraint>(Tmp); 376bd03ef19SGabor Marton } 3773ff220deSGabor Marton 3783ff220deSGabor Marton bool checkSpecificValidity(const FunctionDecl *FD) const override { 3793ff220deSGabor Marton const bool ValidArg = getArgType(FD, ArgN)->isPointerType(); 3803ff220deSGabor Marton assert(ValidArg && 3813ff220deSGabor Marton "This constraint should be applied only on a pointer type"); 3823ff220deSGabor Marton return ValidArg; 3833ff220deSGabor Marton } 384bd03ef19SGabor Marton }; 385bd03ef19SGabor Marton 386c6b8484eSGabor Marton /// The complete list of constraints that defines a single branch. 387c6b8484eSGabor Marton typedef std::vector<ValueConstraintPtr> ConstraintSet; 388bba497fbSArtem Dergachev 389a787a4edSGabor Marton using ArgTypes = std::vector<Optional<QualType>>; 390a787a4edSGabor Marton using RetType = Optional<QualType>; 39116506d78SGabor Marton 39216506d78SGabor Marton // A placeholder type, we use it whenever we do not care about the concrete 39316506d78SGabor Marton // type in a Signature. 39416506d78SGabor Marton const QualType Irrelevant{}; 39516506d78SGabor Marton bool static isIrrelevant(QualType T) { return T.isNull(); } 39616506d78SGabor Marton 39716506d78SGabor Marton // The signature of a function we want to describe with a summary. This is a 39816506d78SGabor Marton // concessive signature, meaning there may be irrelevant types in the 39916506d78SGabor Marton // signature which we do not check against a function with concrete types. 400a787a4edSGabor Marton // All types in the spec need to be canonical. 401a787a4edSGabor Marton class Signature { 402a787a4edSGabor Marton using ArgQualTypes = std::vector<QualType>; 403a787a4edSGabor Marton ArgQualTypes ArgTys; 4043ff220deSGabor Marton QualType RetTy; 405a787a4edSGabor Marton // True if any component type is not found by lookup. 406a787a4edSGabor Marton bool Invalid = false; 407a787a4edSGabor Marton 408a787a4edSGabor Marton public: 409a787a4edSGabor Marton // Construct a signature from optional types. If any of the optional types 410a787a4edSGabor Marton // are not set then the signature will be invalid. 411a787a4edSGabor Marton Signature(ArgTypes ArgTys, RetType RetTy) { 412a787a4edSGabor Marton for (Optional<QualType> Arg : ArgTys) { 413a787a4edSGabor Marton if (!Arg) { 414a787a4edSGabor Marton Invalid = true; 415a787a4edSGabor Marton return; 416a787a4edSGabor Marton } else { 417a787a4edSGabor Marton assertArgTypeSuitableForSignature(*Arg); 418a787a4edSGabor Marton this->ArgTys.push_back(*Arg); 419a787a4edSGabor Marton } 420a787a4edSGabor Marton } 421a787a4edSGabor Marton if (!RetTy) { 422a787a4edSGabor Marton Invalid = true; 423a787a4edSGabor Marton return; 424a787a4edSGabor Marton } else { 425a787a4edSGabor Marton assertRetTypeSuitableForSignature(*RetTy); 426a787a4edSGabor Marton this->RetTy = *RetTy; 42716506d78SGabor Marton } 42816506d78SGabor Marton } 4293ff220deSGabor Marton 430a787a4edSGabor Marton bool isInvalid() const { return Invalid; } 43116506d78SGabor Marton bool matches(const FunctionDecl *FD) const; 43216506d78SGabor Marton 43316506d78SGabor Marton private: 43416506d78SGabor Marton static void assertArgTypeSuitableForSignature(QualType T) { 43516506d78SGabor Marton assert((T.isNull() || !T->isVoidType()) && 43616506d78SGabor Marton "We should have no void types in the spec"); 43716506d78SGabor Marton assert((T.isNull() || T.isCanonical()) && 43816506d78SGabor Marton "We should only have canonical types in the spec"); 43916506d78SGabor Marton } 44016506d78SGabor Marton static void assertRetTypeSuitableForSignature(QualType T) { 44116506d78SGabor Marton assert((T.isNull() || T.isCanonical()) && 44216506d78SGabor Marton "We should only have canonical types in the spec"); 44316506d78SGabor Marton } 44416506d78SGabor Marton }; 44516506d78SGabor Marton 44616506d78SGabor Marton static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) { 44716506d78SGabor Marton assert(FD && "Function must be set"); 44816506d78SGabor Marton QualType T = (ArgN == Ret) 44916506d78SGabor Marton ? FD->getReturnType().getCanonicalType() 45016506d78SGabor Marton : FD->getParamDecl(ArgN)->getType().getCanonicalType(); 45116506d78SGabor Marton return T; 45216506d78SGabor Marton } 45316506d78SGabor Marton 454c6b8484eSGabor Marton using Cases = std::vector<ConstraintSet>; 455f5086b38SGabor Marton 45616506d78SGabor Marton /// A summary includes information about 45716506d78SGabor Marton /// * function prototype (signature) 45894061df6SGabor Marton /// * approach to invalidation, 45994061df6SGabor Marton /// * a list of branches - a list of list of ranges - 46094061df6SGabor Marton /// A branch represents a path in the exploded graph of a function (which 46194061df6SGabor Marton /// is a tree). So, a branch is a series of assumptions. In other words, 46294061df6SGabor Marton /// branches represent split states and additional assumptions on top of 46394061df6SGabor Marton /// the splitting assumption. 46494061df6SGabor Marton /// For example, consider the branches in `isalpha(x)` 46594061df6SGabor Marton /// Branch 1) 46694061df6SGabor Marton /// x is in range ['A', 'Z'] or in ['a', 'z'] 46794061df6SGabor Marton /// then the return value is not 0. (I.e. out-of-range [0, 0]) 46894061df6SGabor Marton /// Branch 2) 46994061df6SGabor Marton /// x is out-of-range ['A', 'Z'] and out-of-range ['a', 'z'] 47094061df6SGabor Marton /// then the return value is 0. 47194061df6SGabor Marton /// * a list of argument constraints, that must be true on every branch. 47294061df6SGabor Marton /// If these constraints are not satisfied that means a fatal error 47394061df6SGabor Marton /// usually resulting in undefined behaviour. 47416506d78SGabor Marton /// 47516506d78SGabor Marton /// Application of a summary: 47616506d78SGabor Marton /// The signature and argument constraints together contain information 47716506d78SGabor Marton /// about which functions are handled by the summary. The signature can use 47816506d78SGabor Marton /// "wildcards", i.e. Irrelevant types. Irrelevant type of a parameter in 47916506d78SGabor Marton /// a signature means that type is not compared to the type of the parameter 48016506d78SGabor Marton /// in the found FunctionDecl. Argument constraints may specify additional 48116506d78SGabor Marton /// rules for the given parameter's type, those rules are checked once the 48216506d78SGabor Marton /// signature is matched. 48316506d78SGabor Marton class Summary { 484f5086b38SGabor Marton const InvalidationKind InvalidationKd; 485c6b8484eSGabor Marton Cases CaseConstraints; 486c6b8484eSGabor Marton ConstraintSet ArgConstraints; 487f5086b38SGabor Marton 48816506d78SGabor Marton // The function to which the summary applies. This is set after lookup and 48916506d78SGabor Marton // match to the signature. 49016506d78SGabor Marton const FunctionDecl *FD = nullptr; 49116506d78SGabor Marton 49216506d78SGabor Marton public: 4933ff220deSGabor Marton Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {} 4943ff220deSGabor Marton 495c6b8484eSGabor Marton Summary &Case(ConstraintSet &&CS) { 496c6b8484eSGabor Marton CaseConstraints.push_back(std::move(CS)); 497f5086b38SGabor Marton return *this; 498f5086b38SGabor Marton } 499b40b3196SGabor Marton Summary &Case(const ConstraintSet &CS) { 500b40b3196SGabor Marton CaseConstraints.push_back(CS); 501b40b3196SGabor Marton return *this; 502b40b3196SGabor Marton } 50394061df6SGabor Marton Summary &ArgConstraint(ValueConstraintPtr VC) { 504a97648b9SGabor Marton assert(VC->getArgNo() != Ret && 505a97648b9SGabor Marton "Arg constraint should not refer to the return value"); 50694061df6SGabor Marton ArgConstraints.push_back(VC); 50794061df6SGabor Marton return *this; 50894061df6SGabor Marton } 509bba497fbSArtem Dergachev 51016506d78SGabor Marton InvalidationKind getInvalidationKd() const { return InvalidationKd; } 51116506d78SGabor Marton const Cases &getCaseConstraints() const { return CaseConstraints; } 51216506d78SGabor Marton const ConstraintSet &getArgConstraints() const { return ArgConstraints; } 513bba497fbSArtem Dergachev 514f5086b38SGabor Marton QualType getArgType(ArgNo ArgN) const { 51516506d78SGabor Marton return StdLibraryFunctionsChecker::getArgType(FD, ArgN); 516bba497fbSArtem Dergachev } 517bba497fbSArtem Dergachev 51816506d78SGabor Marton // Returns true if the summary should be applied to the given function. 51916506d78SGabor Marton // And if yes then store the function declaration. 52011d2e63aSGabor Marton bool matchesAndSet(const Signature &Sign, const FunctionDecl *FD) { 52111d2e63aSGabor Marton bool Result = Sign.matches(FD) && validateByConstraints(FD); 52216506d78SGabor Marton if (Result) { 52316506d78SGabor Marton assert(!this->FD && "FD must not be set more than once"); 52416506d78SGabor Marton this->FD = FD; 52516506d78SGabor Marton } 52616506d78SGabor Marton return Result; 52716506d78SGabor Marton } 52816506d78SGabor Marton 52916506d78SGabor Marton private: 53016506d78SGabor Marton // Once we know the exact type of the function then do sanity check on all 53116506d78SGabor Marton // the given constraints. 53216506d78SGabor Marton bool validateByConstraints(const FunctionDecl *FD) const { 53316506d78SGabor Marton for (const ConstraintSet &Case : CaseConstraints) 53416506d78SGabor Marton for (const ValueConstraintPtr &Constraint : Case) 53516506d78SGabor Marton if (!Constraint->checkValidity(FD)) 53616506d78SGabor Marton return false; 53716506d78SGabor Marton for (const ValueConstraintPtr &Constraint : ArgConstraints) 53816506d78SGabor Marton if (!Constraint->checkValidity(FD)) 53916506d78SGabor Marton return false; 54016506d78SGabor Marton return true; 54116506d78SGabor Marton } 542bba497fbSArtem Dergachev }; 543bba497fbSArtem Dergachev 544bba497fbSArtem Dergachev // The map of all functions supported by the checker. It is initialized 545bba497fbSArtem Dergachev // lazily, and it doesn't change after initialization. 54662e747f6SGabor Marton using FunctionSummaryMapType = llvm::DenseMap<const FunctionDecl *, Summary>; 54762e747f6SGabor Marton mutable FunctionSummaryMapType FunctionSummaryMap; 548bba497fbSArtem Dergachev 54994061df6SGabor Marton mutable std::unique_ptr<BugType> BT_InvalidArg; 550c7635040SValeriy Savchenko mutable bool SummariesInitialized = false; 55194061df6SGabor Marton 552f5086b38SGabor Marton static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) { 553f5086b38SGabor Marton return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN); 554bba497fbSArtem Dergachev } 555bba497fbSArtem Dergachev 556bba497fbSArtem Dergachev public: 55794061df6SGabor Marton void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 558bba497fbSArtem Dergachev void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 55944820630SArtem Dergachev bool evalCall(const CallEvent &Call, CheckerContext &C) const; 560bba497fbSArtem Dergachev 5611525232eSGabor Marton enum CheckKind { 5621525232eSGabor Marton CK_StdCLibraryFunctionArgsChecker, 5631525232eSGabor Marton CK_StdCLibraryFunctionsTesterChecker, 5641525232eSGabor Marton CK_NumCheckKinds 5651525232eSGabor Marton }; 56694061df6SGabor Marton DefaultBool ChecksEnabled[CK_NumCheckKinds]; 56794061df6SGabor Marton CheckerNameRef CheckNames[CK_NumCheckKinds]; 56894061df6SGabor Marton 569ff4492c8SGabor Marton bool DisplayLoadedSummaries = false; 570db4d5f70SGabor Marton bool ModelPOSIX = false; 571*edde4efcSBalazs Benics bool ShouldAssumeControlledEnvironment = false; 572ff4492c8SGabor Marton 573bba497fbSArtem Dergachev private: 574f5086b38SGabor Marton Optional<Summary> findFunctionSummary(const FunctionDecl *FD, 575bba497fbSArtem Dergachev CheckerContext &C) const; 57694061df6SGabor Marton Optional<Summary> findFunctionSummary(const CallEvent &Call, 57794061df6SGabor Marton CheckerContext &C) const; 578bba497fbSArtem Dergachev 579536456a7SGabor Marton void initFunctionSummaries(CheckerContext &C) const; 58094061df6SGabor Marton 58194061df6SGabor Marton void reportBug(const CallEvent &Call, ExplodedNode *N, 582a7cb951fSGabor Marton const ValueConstraint *VC, const Summary &Summary, 583a7cb951fSGabor Marton CheckerContext &C) const { 58494061df6SGabor Marton if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker]) 58594061df6SGabor Marton return; 586a97648b9SGabor Marton std::string Msg = 587a97648b9SGabor Marton (Twine("Function argument constraint is not satisfied, constraint: ") + 588a7cb951fSGabor Marton VC->getName().data()) 589a97648b9SGabor Marton .str(); 59094061df6SGabor Marton if (!BT_InvalidArg) 59194061df6SGabor Marton BT_InvalidArg = std::make_unique<BugType>( 59294061df6SGabor Marton CheckNames[CK_StdCLibraryFunctionArgsChecker], 59394061df6SGabor Marton "Unsatisfied argument constraints", categories::LogicError); 59494061df6SGabor Marton auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N); 5954b99f9c7SGabor Marton 5964b99f9c7SGabor Marton for (ArgNo ArgN : VC->getArgsToTrack()) 5974b99f9c7SGabor Marton bugreporter::trackExpressionValue(N, Call.getArgExpr(ArgN), *R); 598a97648b9SGabor Marton 599a97648b9SGabor Marton // Highlight the range of the argument that was violated. 600a97648b9SGabor Marton R->addRange(Call.getArgSourceRange(VC->getArgNo())); 601a97648b9SGabor Marton 602a7cb951fSGabor Marton // Describe the argument constraint in a note. 603a7cb951fSGabor Marton R->addNote(VC->describe(C.getState(), Summary), R->getLocation(), 604a7cb951fSGabor Marton Call.getArgSourceRange(VC->getArgNo())); 605a7cb951fSGabor Marton 60694061df6SGabor Marton C.emitReport(std::move(R)); 60794061df6SGabor Marton } 608bba497fbSArtem Dergachev }; 609c6b8484eSGabor Marton 610c6b8484eSGabor Marton const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret = 611c6b8484eSGabor Marton std::numeric_limits<ArgNo>::max(); 612c6b8484eSGabor Marton 613bba497fbSArtem Dergachev } // end of anonymous namespace 614bba497fbSArtem Dergachev 615a7cb951fSGabor Marton static BasicValueFactory &getBVF(ProgramStateRef State) { 616a7cb951fSGabor Marton ProgramStateManager &Mgr = State->getStateManager(); 617a7cb951fSGabor Marton SValBuilder &SVB = Mgr.getSValBuilder(); 618a7cb951fSGabor Marton return SVB.getBasicValueFactory(); 619a7cb951fSGabor Marton } 620a7cb951fSGabor Marton 621a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::NotNullConstraint::describe( 622a7cb951fSGabor Marton ProgramStateRef State, const Summary &Summary) const { 623a7cb951fSGabor Marton SmallString<48> Result; 624a7cb951fSGabor Marton Result += "The "; 625a7cb951fSGabor Marton Result += getArgDesc(ArgN); 626a7cb951fSGabor Marton Result += " should not be NULL"; 627a7cb951fSGabor Marton return Result.c_str(); 628a7cb951fSGabor Marton } 629a7cb951fSGabor Marton 630a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::RangeConstraint::describe( 631a7cb951fSGabor Marton ProgramStateRef State, const Summary &Summary) const { 632a7cb951fSGabor Marton 633a7cb951fSGabor Marton BasicValueFactory &BVF = getBVF(State); 634a7cb951fSGabor Marton 635a7cb951fSGabor Marton QualType T = Summary.getArgType(getArgNo()); 636a7cb951fSGabor Marton SmallString<48> Result; 637a7cb951fSGabor Marton Result += "The "; 638a7cb951fSGabor Marton Result += getArgDesc(ArgN); 639a7cb951fSGabor Marton Result += " should be "; 640a7cb951fSGabor Marton 641a7cb951fSGabor Marton // Range kind as a string. 642a7cb951fSGabor Marton Kind == OutOfRange ? Result += "out of" : Result += "within"; 643a7cb951fSGabor Marton 644a7cb951fSGabor Marton // Get the range values as a string. 645a7cb951fSGabor Marton Result += " the range "; 646a7cb951fSGabor Marton if (Ranges.size() > 1) 647a7cb951fSGabor Marton Result += "["; 648a7cb951fSGabor Marton unsigned I = Ranges.size(); 649a7cb951fSGabor Marton for (const std::pair<RangeInt, RangeInt> &R : Ranges) { 650a7cb951fSGabor Marton Result += "["; 651a7cb951fSGabor Marton const llvm::APSInt &Min = BVF.getValue(R.first, T); 652a7cb951fSGabor Marton const llvm::APSInt &Max = BVF.getValue(R.second, T); 653a7cb951fSGabor Marton Min.toString(Result); 654a7cb951fSGabor Marton Result += ", "; 655a7cb951fSGabor Marton Max.toString(Result); 656a7cb951fSGabor Marton Result += "]"; 657a7cb951fSGabor Marton if (--I > 0) 658a7cb951fSGabor Marton Result += ", "; 659a7cb951fSGabor Marton } 660a7cb951fSGabor Marton if (Ranges.size() > 1) 661a7cb951fSGabor Marton Result += "]"; 662a7cb951fSGabor Marton 663a7cb951fSGabor Marton return Result.c_str(); 664a7cb951fSGabor Marton } 665a7cb951fSGabor Marton 666a7cb951fSGabor Marton SmallString<8> 667a7cb951fSGabor Marton StdLibraryFunctionsChecker::getArgDesc(StdLibraryFunctionsChecker::ArgNo ArgN) { 668a7cb951fSGabor Marton SmallString<8> Result; 669a7cb951fSGabor Marton Result += std::to_string(ArgN + 1); 670a7cb951fSGabor Marton Result += llvm::getOrdinalSuffix(ArgN + 1); 671a7cb951fSGabor Marton Result += " arg"; 672a7cb951fSGabor Marton return Result; 673a7cb951fSGabor Marton } 674a7cb951fSGabor Marton 675a7cb951fSGabor Marton std::string StdLibraryFunctionsChecker::BufferSizeConstraint::describe( 676a7cb951fSGabor Marton ProgramStateRef State, const Summary &Summary) const { 677a7cb951fSGabor Marton SmallString<96> Result; 678a7cb951fSGabor Marton Result += "The size of the "; 679a7cb951fSGabor Marton Result += getArgDesc(ArgN); 680a7cb951fSGabor Marton Result += " should be equal to or less than the value of "; 681a7cb951fSGabor Marton if (ConcreteSize) { 682a7cb951fSGabor Marton ConcreteSize->toString(Result); 683a7cb951fSGabor Marton } else if (SizeArgN) { 684a7cb951fSGabor Marton Result += "the "; 685a7cb951fSGabor Marton Result += getArgDesc(*SizeArgN); 686a7cb951fSGabor Marton if (SizeMultiplierArgN) { 687a7cb951fSGabor Marton Result += " times the "; 688a7cb951fSGabor Marton Result += getArgDesc(*SizeMultiplierArgN); 689a7cb951fSGabor Marton } 690a7cb951fSGabor Marton } 691a7cb951fSGabor Marton return Result.c_str(); 692a7cb951fSGabor Marton } 693a7cb951fSGabor Marton 694c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange( 695bba497fbSArtem Dergachev ProgramStateRef State, const CallEvent &Call, 696f5086b38SGabor Marton const Summary &Summary) const { 697a787a4edSGabor Marton if (Ranges.empty()) 698a787a4edSGabor Marton return State; 699bba497fbSArtem Dergachev 700bba497fbSArtem Dergachev ProgramStateManager &Mgr = State->getStateManager(); 701bba497fbSArtem Dergachev SValBuilder &SVB = Mgr.getSValBuilder(); 702bba497fbSArtem Dergachev BasicValueFactory &BVF = SVB.getBasicValueFactory(); 703bba497fbSArtem Dergachev ConstraintManager &CM = Mgr.getConstraintManager(); 70416506d78SGabor Marton QualType T = Summary.getArgType(getArgNo()); 705bba497fbSArtem Dergachev SVal V = getArgSVal(Call, getArgNo()); 706bba497fbSArtem Dergachev 707bba497fbSArtem Dergachev if (auto N = V.getAs<NonLoc>()) { 708f5086b38SGabor Marton const IntRangeVector &R = getRanges(); 709bba497fbSArtem Dergachev size_t E = R.size(); 710bba497fbSArtem Dergachev for (size_t I = 0; I != E; ++I) { 711bba497fbSArtem Dergachev const llvm::APSInt &Min = BVF.getValue(R[I].first, T); 712bba497fbSArtem Dergachev const llvm::APSInt &Max = BVF.getValue(R[I].second, T); 713bba497fbSArtem Dergachev assert(Min <= Max); 7143f8c3fa7SDominic Chen State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 715bba497fbSArtem Dergachev if (!State) 716bba497fbSArtem Dergachev break; 717bba497fbSArtem Dergachev } 718bba497fbSArtem Dergachev } 719bba497fbSArtem Dergachev 720bba497fbSArtem Dergachev return State; 721bba497fbSArtem Dergachev } 722bba497fbSArtem Dergachev 723c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange( 724bba497fbSArtem Dergachev ProgramStateRef State, const CallEvent &Call, 725f5086b38SGabor Marton const Summary &Summary) const { 726a787a4edSGabor Marton if (Ranges.empty()) 727a787a4edSGabor Marton return State; 728bba497fbSArtem Dergachev 729bba497fbSArtem Dergachev ProgramStateManager &Mgr = State->getStateManager(); 730bba497fbSArtem Dergachev SValBuilder &SVB = Mgr.getSValBuilder(); 731bba497fbSArtem Dergachev BasicValueFactory &BVF = SVB.getBasicValueFactory(); 732bba497fbSArtem Dergachev ConstraintManager &CM = Mgr.getConstraintManager(); 73316506d78SGabor Marton QualType T = Summary.getArgType(getArgNo()); 734bba497fbSArtem Dergachev SVal V = getArgSVal(Call, getArgNo()); 735bba497fbSArtem Dergachev 736bba497fbSArtem Dergachev // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R". 737bba497fbSArtem Dergachev // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary, 738bba497fbSArtem Dergachev // and then cut away all holes in R one by one. 739536456a7SGabor Marton // 740536456a7SGabor Marton // E.g. consider a range list R as [A, B] and [C, D] 741536456a7SGabor Marton // -------+--------+------------------+------------+-----------> 742536456a7SGabor Marton // A B C D 743536456a7SGabor Marton // Then we assume that the value is not in [-inf, A - 1], 744536456a7SGabor Marton // then not in [D + 1, +inf], then not in [B + 1, C - 1] 745bba497fbSArtem Dergachev if (auto N = V.getAs<NonLoc>()) { 746f5086b38SGabor Marton const IntRangeVector &R = getRanges(); 747bba497fbSArtem Dergachev size_t E = R.size(); 748bba497fbSArtem Dergachev 749bba497fbSArtem Dergachev const llvm::APSInt &MinusInf = BVF.getMinValue(T); 750bba497fbSArtem Dergachev const llvm::APSInt &PlusInf = BVF.getMaxValue(T); 751bba497fbSArtem Dergachev 75226b0a9d8SArtem Dergachev const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T); 753bba497fbSArtem Dergachev if (Left != PlusInf) { 754bba497fbSArtem Dergachev assert(MinusInf <= Left); 7553f8c3fa7SDominic Chen State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false); 756bba497fbSArtem Dergachev if (!State) 757bba497fbSArtem Dergachev return nullptr; 758bba497fbSArtem Dergachev } 759bba497fbSArtem Dergachev 76026b0a9d8SArtem Dergachev const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T); 761bba497fbSArtem Dergachev if (Right != MinusInf) { 762bba497fbSArtem Dergachev assert(Right <= PlusInf); 7633f8c3fa7SDominic Chen State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false); 764bba497fbSArtem Dergachev if (!State) 765bba497fbSArtem Dergachev return nullptr; 766bba497fbSArtem Dergachev } 767bba497fbSArtem Dergachev 768bba497fbSArtem Dergachev for (size_t I = 1; I != E; ++I) { 76926b0a9d8SArtem Dergachev const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T); 77026b0a9d8SArtem Dergachev const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T); 771536456a7SGabor Marton if (Min <= Max) { 7723f8c3fa7SDominic Chen State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 773bba497fbSArtem Dergachev if (!State) 774bba497fbSArtem Dergachev return nullptr; 775bba497fbSArtem Dergachev } 776bba497fbSArtem Dergachev } 777536456a7SGabor Marton } 778bba497fbSArtem Dergachev 779bba497fbSArtem Dergachev return State; 780bba497fbSArtem Dergachev } 781bba497fbSArtem Dergachev 782c6b8484eSGabor Marton ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply( 783bd03ef19SGabor Marton ProgramStateRef State, const CallEvent &Call, const Summary &Summary, 784bd03ef19SGabor Marton CheckerContext &C) const { 785bba497fbSArtem Dergachev 786bba497fbSArtem Dergachev ProgramStateManager &Mgr = State->getStateManager(); 787bba497fbSArtem Dergachev SValBuilder &SVB = Mgr.getSValBuilder(); 788bba497fbSArtem Dergachev QualType CondT = SVB.getConditionType(); 78916506d78SGabor Marton QualType T = Summary.getArgType(getArgNo()); 790bba497fbSArtem Dergachev SVal V = getArgSVal(Call, getArgNo()); 791bba497fbSArtem Dergachev 792bba497fbSArtem Dergachev BinaryOperator::Opcode Op = getOpcode(); 793f5086b38SGabor Marton ArgNo OtherArg = getOtherArgNo(); 794bba497fbSArtem Dergachev SVal OtherV = getArgSVal(Call, OtherArg); 79516506d78SGabor Marton QualType OtherT = Summary.getArgType(OtherArg); 796bba497fbSArtem Dergachev // Note: we avoid integral promotion for comparison. 797bba497fbSArtem Dergachev OtherV = SVB.evalCast(OtherV, T, OtherT); 798bba497fbSArtem Dergachev if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT) 799bba497fbSArtem Dergachev .getAs<DefinedOrUnknownSVal>()) 800bba497fbSArtem Dergachev State = State->assume(*CompV, true); 801bba497fbSArtem Dergachev return State; 802bba497fbSArtem Dergachev } 803bba497fbSArtem Dergachev 80494061df6SGabor Marton void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call, 80594061df6SGabor Marton CheckerContext &C) const { 80694061df6SGabor Marton Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 80794061df6SGabor Marton if (!FoundSummary) 80894061df6SGabor Marton return; 80994061df6SGabor Marton 81094061df6SGabor Marton const Summary &Summary = *FoundSummary; 81194061df6SGabor Marton ProgramStateRef State = C.getState(); 81294061df6SGabor Marton 8131525232eSGabor Marton ProgramStateRef NewState = State; 81416506d78SGabor Marton for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) { 81516506d78SGabor Marton ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C); 81616506d78SGabor Marton ProgramStateRef FailureSt = 81716506d78SGabor Marton Constraint->negate()->apply(NewState, Call, Summary, C); 81894061df6SGabor Marton // The argument constraint is not satisfied. 81994061df6SGabor Marton if (FailureSt && !SuccessSt) { 8201525232eSGabor Marton if (ExplodedNode *N = C.generateErrorNode(NewState)) 821a7cb951fSGabor Marton reportBug(Call, N, Constraint.get(), Summary, C); 82294061df6SGabor Marton break; 82394061df6SGabor Marton } else { 8241525232eSGabor Marton // We will apply the constraint even if we cannot reason about the 8251525232eSGabor Marton // argument. This means both SuccessSt and FailureSt can be true. If we 8261525232eSGabor Marton // weren't applying the constraint that would mean that symbolic 8271525232eSGabor Marton // execution continues on a code whose behaviour is undefined. 82894061df6SGabor Marton assert(SuccessSt); 8291525232eSGabor Marton NewState = SuccessSt; 83094061df6SGabor Marton } 83194061df6SGabor Marton } 8321525232eSGabor Marton if (NewState && NewState != State) 8331525232eSGabor Marton C.addTransition(NewState); 83494061df6SGabor Marton } 83594061df6SGabor Marton 836bba497fbSArtem Dergachev void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call, 837bba497fbSArtem Dergachev CheckerContext &C) const { 83894061df6SGabor Marton Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 839bba497fbSArtem Dergachev if (!FoundSummary) 840bba497fbSArtem Dergachev return; 841bba497fbSArtem Dergachev 842c6b8484eSGabor Marton // Now apply the constraints. 843f5086b38SGabor Marton const Summary &Summary = *FoundSummary; 844bba497fbSArtem Dergachev ProgramStateRef State = C.getState(); 845bba497fbSArtem Dergachev 846f5086b38SGabor Marton // Apply case/branch specifications. 84716506d78SGabor Marton for (const ConstraintSet &Case : Summary.getCaseConstraints()) { 848bba497fbSArtem Dergachev ProgramStateRef NewState = State; 84916506d78SGabor Marton for (const ValueConstraintPtr &Constraint : Case) { 85016506d78SGabor Marton NewState = Constraint->apply(NewState, Call, Summary, C); 851bba497fbSArtem Dergachev if (!NewState) 852bba497fbSArtem Dergachev break; 853bba497fbSArtem Dergachev } 854bba497fbSArtem Dergachev 855bba497fbSArtem Dergachev if (NewState && NewState != State) 856bba497fbSArtem Dergachev C.addTransition(NewState); 857bba497fbSArtem Dergachev } 858bba497fbSArtem Dergachev } 859bba497fbSArtem Dergachev 86044820630SArtem Dergachev bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call, 861bba497fbSArtem Dergachev CheckerContext &C) const { 86294061df6SGabor Marton Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 863bba497fbSArtem Dergachev if (!FoundSummary) 864bba497fbSArtem Dergachev return false; 865bba497fbSArtem Dergachev 866f5086b38SGabor Marton const Summary &Summary = *FoundSummary; 86716506d78SGabor Marton switch (Summary.getInvalidationKd()) { 868bba497fbSArtem Dergachev case EvalCallAsPure: { 869bba497fbSArtem Dergachev ProgramStateRef State = C.getState(); 870bba497fbSArtem Dergachev const LocationContext *LC = C.getLocationContext(); 871879c12d9SSimon Pilgrim const auto *CE = cast<CallExpr>(Call.getOriginExpr()); 872bba497fbSArtem Dergachev SVal V = C.getSValBuilder().conjureSymbolVal( 873bba497fbSArtem Dergachev CE, LC, CE->getType().getCanonicalType(), C.blockCount()); 874bba497fbSArtem Dergachev State = State->BindExpr(CE, LC, V); 875bba497fbSArtem Dergachev C.addTransition(State); 876bba497fbSArtem Dergachev return true; 877bba497fbSArtem Dergachev } 878bba497fbSArtem Dergachev case NoEvalCall: 879bba497fbSArtem Dergachev // Summary tells us to avoid performing eval::Call. The function is possibly 880bba497fbSArtem Dergachev // evaluated by another checker, or evaluated conservatively. 881bba497fbSArtem Dergachev return false; 882bba497fbSArtem Dergachev } 883bba497fbSArtem Dergachev llvm_unreachable("Unknown invalidation kind!"); 884bba497fbSArtem Dergachev } 885bba497fbSArtem Dergachev 88616506d78SGabor Marton bool StdLibraryFunctionsChecker::Signature::matches( 8878f961399SGabor Marton const FunctionDecl *FD) const { 888a787a4edSGabor Marton assert(!isInvalid()); 889fe0972d3SGabor Marton // Check the number of arguments. 8908f961399SGabor Marton if (FD->param_size() != ArgTys.size()) 891bba497fbSArtem Dergachev return false; 892bba497fbSArtem Dergachev 893fe0972d3SGabor Marton // The "restrict" keyword is illegal in C++, however, many libc 894fe0972d3SGabor Marton // implementations use the "__restrict" compiler intrinsic in functions 895fe0972d3SGabor Marton // prototypes. The "__restrict" keyword qualifies a type as a restricted type 896fe0972d3SGabor Marton // even in C++. 897fe0972d3SGabor Marton // In case of any non-C99 languages, we don't want to match based on the 898fe0972d3SGabor Marton // restrict qualifier because we cannot know if the given libc implementation 899fe0972d3SGabor Marton // qualifies the paramter type or not. 900fe0972d3SGabor Marton auto RemoveRestrict = [&FD](QualType T) { 901fe0972d3SGabor Marton if (!FD->getASTContext().getLangOpts().C99) 902fe0972d3SGabor Marton T.removeLocalRestrict(); 903fe0972d3SGabor Marton return T; 904fe0972d3SGabor Marton }; 905bba497fbSArtem Dergachev 906fe0972d3SGabor Marton // Check the return type. 907fe0972d3SGabor Marton if (!isIrrelevant(RetTy)) { 908fe0972d3SGabor Marton QualType FDRetTy = RemoveRestrict(FD->getReturnType().getCanonicalType()); 909fe0972d3SGabor Marton if (RetTy != FDRetTy) 910fe0972d3SGabor Marton return false; 911fe0972d3SGabor Marton } 912fe0972d3SGabor Marton 913fe0972d3SGabor Marton // Check the argument types. 914f5086b38SGabor Marton for (size_t I = 0, E = ArgTys.size(); I != E; ++I) { 91516506d78SGabor Marton QualType ArgTy = ArgTys[I]; 91616506d78SGabor Marton if (isIrrelevant(ArgTy)) 917bba497fbSArtem Dergachev continue; 918fe0972d3SGabor Marton QualType FDArgTy = 919fe0972d3SGabor Marton RemoveRestrict(FD->getParamDecl(I)->getType().getCanonicalType()); 920fe0972d3SGabor Marton if (ArgTy != FDArgTy) 921bba497fbSArtem Dergachev return false; 922bba497fbSArtem Dergachev } 923bba497fbSArtem Dergachev 924bba497fbSArtem Dergachev return true; 925bba497fbSArtem Dergachev } 926bba497fbSArtem Dergachev 927f5086b38SGabor Marton Optional<StdLibraryFunctionsChecker::Summary> 928bba497fbSArtem Dergachev StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD, 929bba497fbSArtem Dergachev CheckerContext &C) const { 930bba497fbSArtem Dergachev if (!FD) 931bba497fbSArtem Dergachev return None; 932bba497fbSArtem Dergachev 933536456a7SGabor Marton initFunctionSummaries(C); 934bba497fbSArtem Dergachev 93562e747f6SGabor Marton auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl()); 936bba497fbSArtem Dergachev if (FSMI == FunctionSummaryMap.end()) 937bba497fbSArtem Dergachev return None; 93862e747f6SGabor Marton return FSMI->second; 939bba497fbSArtem Dergachev } 940bba497fbSArtem Dergachev 94194061df6SGabor Marton Optional<StdLibraryFunctionsChecker::Summary> 94294061df6SGabor Marton StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call, 94394061df6SGabor Marton CheckerContext &C) const { 94494061df6SGabor Marton const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); 94594061df6SGabor Marton if (!FD) 94694061df6SGabor Marton return None; 9478f961399SGabor Marton return findFunctionSummary(FD, C); 94894061df6SGabor Marton } 94994061df6SGabor Marton 950a787a4edSGabor Marton void StdLibraryFunctionsChecker::initFunctionSummaries( 951a787a4edSGabor Marton CheckerContext &C) const { 952c7635040SValeriy Savchenko if (SummariesInitialized) 953a787a4edSGabor Marton return; 954a787a4edSGabor Marton 955a787a4edSGabor Marton SValBuilder &SVB = C.getSValBuilder(); 956a787a4edSGabor Marton BasicValueFactory &BVF = SVB.getBasicValueFactory(); 957a787a4edSGabor Marton const ASTContext &ACtx = BVF.getContext(); 958a787a4edSGabor Marton 959a787a4edSGabor Marton // Helper class to lookup a type by its name. 960a787a4edSGabor Marton class LookupType { 961a787a4edSGabor Marton const ASTContext &ACtx; 962a787a4edSGabor Marton 963a787a4edSGabor Marton public: 964a787a4edSGabor Marton LookupType(const ASTContext &ACtx) : ACtx(ACtx) {} 965a787a4edSGabor Marton 966a787a4edSGabor Marton // Find the type. If not found then the optional is not set. 967a787a4edSGabor Marton llvm::Optional<QualType> operator()(StringRef Name) { 968634258b8SGabor Marton IdentifierInfo &II = ACtx.Idents.get(Name); 969634258b8SGabor Marton auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); 9700cb7e7caSVassil Vassilev if (LookupRes.empty()) 971634258b8SGabor Marton return None; 972634258b8SGabor Marton 973634258b8SGabor Marton // Prioritze typedef declarations. 974634258b8SGabor Marton // This is needed in case of C struct typedefs. E.g.: 975634258b8SGabor Marton // typedef struct FILE FILE; 976a787a4edSGabor Marton // In this case, we have a RecordDecl 'struct FILE' with the name 'FILE' 977a787a4edSGabor Marton // and we have a TypedefDecl with the name 'FILE'. 978db4d5f70SGabor Marton for (Decl *D : LookupRes) 979634258b8SGabor Marton if (auto *TD = dyn_cast<TypedefNameDecl>(D)) 980634258b8SGabor Marton return ACtx.getTypeDeclType(TD).getCanonicalType(); 981db4d5f70SGabor Marton 982db4d5f70SGabor Marton // Find the first TypeDecl. 983db4d5f70SGabor Marton // There maybe cases when a function has the same name as a struct. 984db4d5f70SGabor Marton // E.g. in POSIX: `struct stat` and the function `stat()`: 985db4d5f70SGabor Marton // int stat(const char *restrict path, struct stat *restrict buf); 986db4d5f70SGabor Marton for (Decl *D : LookupRes) 987db4d5f70SGabor Marton if (auto *TD = dyn_cast<TypeDecl>(D)) 988db4d5f70SGabor Marton return ACtx.getTypeDeclType(TD).getCanonicalType(); 989db4d5f70SGabor Marton return None; 990634258b8SGabor Marton } 991a787a4edSGabor Marton } lookupTy(ACtx); 992634258b8SGabor Marton 993a787a4edSGabor Marton // Below are auxiliary classes to handle optional types that we get as a 994a787a4edSGabor Marton // result of the lookup. 995a787a4edSGabor Marton class GetRestrictTy { 996a787a4edSGabor Marton const ASTContext &ACtx; 997bba497fbSArtem Dergachev 998a787a4edSGabor Marton public: 999a787a4edSGabor Marton GetRestrictTy(const ASTContext &ACtx) : ACtx(ACtx) {} 1000a787a4edSGabor Marton QualType operator()(QualType Ty) { 10013ff220deSGabor Marton return ACtx.getLangOpts().C99 ? ACtx.getRestrictType(Ty) : Ty; 1002a787a4edSGabor Marton } 1003a787a4edSGabor Marton Optional<QualType> operator()(Optional<QualType> Ty) { 1004a787a4edSGabor Marton if (Ty) 1005a787a4edSGabor Marton return operator()(*Ty); 1006a787a4edSGabor Marton return None; 1007a787a4edSGabor Marton } 1008a787a4edSGabor Marton } getRestrictTy(ACtx); 1009a787a4edSGabor Marton class GetPointerTy { 1010a787a4edSGabor Marton const ASTContext &ACtx; 1011a787a4edSGabor Marton 1012a787a4edSGabor Marton public: 1013a787a4edSGabor Marton GetPointerTy(const ASTContext &ACtx) : ACtx(ACtx) {} 1014a787a4edSGabor Marton QualType operator()(QualType Ty) { return ACtx.getPointerType(Ty); } 1015a787a4edSGabor Marton Optional<QualType> operator()(Optional<QualType> Ty) { 1016a787a4edSGabor Marton if (Ty) 1017a787a4edSGabor Marton return operator()(*Ty); 1018a787a4edSGabor Marton return None; 1019a787a4edSGabor Marton } 1020a787a4edSGabor Marton } getPointerTy(ACtx); 1021a787a4edSGabor Marton class { 1022a787a4edSGabor Marton public: 1023a787a4edSGabor Marton Optional<QualType> operator()(Optional<QualType> Ty) { 1024a787a4edSGabor Marton return Ty ? Optional<QualType>(Ty->withConst()) : None; 1025a787a4edSGabor Marton } 1026a787a4edSGabor Marton QualType operator()(QualType Ty) { return Ty.withConst(); } 1027a787a4edSGabor Marton } getConstTy; 1028a787a4edSGabor Marton class GetMaxValue { 1029a787a4edSGabor Marton BasicValueFactory &BVF; 1030a787a4edSGabor Marton 1031a787a4edSGabor Marton public: 1032a787a4edSGabor Marton GetMaxValue(BasicValueFactory &BVF) : BVF(BVF) {} 1033a787a4edSGabor Marton Optional<RangeInt> operator()(QualType Ty) { 1034a787a4edSGabor Marton return BVF.getMaxValue(Ty).getLimitedValue(); 1035a787a4edSGabor Marton } 1036a787a4edSGabor Marton Optional<RangeInt> operator()(Optional<QualType> Ty) { 1037a787a4edSGabor Marton if (Ty) { 1038a787a4edSGabor Marton return operator()(*Ty); 1039a787a4edSGabor Marton } 1040a787a4edSGabor Marton return None; 1041a787a4edSGabor Marton } 1042a787a4edSGabor Marton } getMaxValue(BVF); 10433ff220deSGabor Marton 1044bba497fbSArtem Dergachev // These types are useful for writing specifications quickly, 1045bba497fbSArtem Dergachev // New specifications should probably introduce more types. 104647fec16cSArtem Dergachev // Some types are hard to obtain from the AST, eg. "ssize_t". 104747fec16cSArtem Dergachev // In such cases it should be possible to provide multiple variants 104847fec16cSArtem Dergachev // of function summary for common cases (eg. ssize_t could be int or long 104947fec16cSArtem Dergachev // or long long, so three summary variants would be enough). 105047fec16cSArtem Dergachev // Of course, function variants are also useful for C++ overloads. 1051db4d5f70SGabor Marton const QualType VoidTy = ACtx.VoidTy; 1052a787a4edSGabor Marton const QualType CharTy = ACtx.CharTy; 1053a787a4edSGabor Marton const QualType WCharTy = ACtx.WCharTy; 1054536456a7SGabor Marton const QualType IntTy = ACtx.IntTy; 1055db4d5f70SGabor Marton const QualType UnsignedIntTy = ACtx.UnsignedIntTy; 1056536456a7SGabor Marton const QualType LongTy = ACtx.LongTy; 1057536456a7SGabor Marton const QualType SizeTy = ACtx.getSizeType(); 1058db4d5f70SGabor Marton 1059a787a4edSGabor Marton const QualType VoidPtrTy = getPointerTy(VoidTy); // void * 1060a787a4edSGabor Marton const QualType IntPtrTy = getPointerTy(IntTy); // int * 1061db4d5f70SGabor Marton const QualType UnsignedIntPtrTy = 1062a787a4edSGabor Marton getPointerTy(UnsignedIntTy); // unsigned int * 10633ff220deSGabor Marton const QualType VoidPtrRestrictTy = getRestrictTy(VoidPtrTy); 1064ededa65dSGabor Marton const QualType ConstVoidPtrTy = 1065a787a4edSGabor Marton getPointerTy(getConstTy(VoidTy)); // const void * 1066a787a4edSGabor Marton const QualType CharPtrTy = getPointerTy(CharTy); // char * 10673ff220deSGabor Marton const QualType CharPtrRestrictTy = getRestrictTy(CharPtrTy); 10688f961399SGabor Marton const QualType ConstCharPtrTy = 1069a787a4edSGabor Marton getPointerTy(getConstTy(CharTy)); // const char * 10703ff220deSGabor Marton const QualType ConstCharPtrRestrictTy = getRestrictTy(ConstCharPtrTy); 1071a787a4edSGabor Marton const QualType Wchar_tPtrTy = getPointerTy(WCharTy); // wchar_t * 1072db4d5f70SGabor Marton const QualType ConstWchar_tPtrTy = 1073a787a4edSGabor Marton getPointerTy(getConstTy(WCharTy)); // const wchar_t * 10743ff220deSGabor Marton const QualType ConstVoidPtrRestrictTy = getRestrictTy(ConstVoidPtrTy); 1075d0128058SGabor Marton const QualType SizePtrTy = getPointerTy(SizeTy); 1076d0128058SGabor Marton const QualType SizePtrRestrictTy = getRestrictTy(SizePtrTy); 1077bba497fbSArtem Dergachev 1078536456a7SGabor Marton const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); 1079db4d5f70SGabor Marton const RangeInt UnsignedIntMax = 1080db4d5f70SGabor Marton BVF.getMaxValue(UnsignedIntTy).getLimitedValue(); 1081536456a7SGabor Marton const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue(); 1082db4d5f70SGabor Marton const RangeInt SizeMax = BVF.getMaxValue(SizeTy).getLimitedValue(); 1083536456a7SGabor Marton 10840eba5dc8SArtem Dergachev // Set UCharRangeMax to min of int or uchar maximum value. 10850eba5dc8SArtem Dergachev // The C standard states that the arguments of functions like isalpha must 10860eba5dc8SArtem Dergachev // be representable as an unsigned char. Their type is 'int', so the max 10870eba5dc8SArtem Dergachev // value of the argument should be min(UCharMax, IntMax). This just happen 10880eba5dc8SArtem Dergachev // to be true for commonly used and well tested instruction set 10890eba5dc8SArtem Dergachev // architectures, but not for others. 10900eba5dc8SArtem Dergachev const RangeInt UCharRangeMax = 10910eba5dc8SArtem Dergachev std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax); 1092536456a7SGabor Marton 1093536456a7SGabor Marton // The platform dependent value of EOF. 1094536456a7SGabor Marton // Try our best to parse this from the Preprocessor, otherwise fallback to -1. 1095536456a7SGabor Marton const auto EOFv = [&C]() -> RangeInt { 1096536456a7SGabor Marton if (const llvm::Optional<int> OptInt = 1097536456a7SGabor Marton tryExpandAsInteger("EOF", C.getPreprocessor())) 1098536456a7SGabor Marton return *OptInt; 1099536456a7SGabor Marton return -1; 1100536456a7SGabor Marton }(); 1101bba497fbSArtem Dergachev 110262e747f6SGabor Marton // Auxiliary class to aid adding summaries to the summary map. 110362e747f6SGabor Marton struct AddToFunctionSummaryMap { 110462e747f6SGabor Marton const ASTContext &ACtx; 110562e747f6SGabor Marton FunctionSummaryMapType ⤅ 1106ff4492c8SGabor Marton bool DisplayLoadedSummaries; 1107ff4492c8SGabor Marton AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM, 1108ff4492c8SGabor Marton bool DisplayLoadedSummaries) 1109ff4492c8SGabor Marton : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) { 1110ff4492c8SGabor Marton } 1111ff4492c8SGabor Marton 111262e747f6SGabor Marton // Add a summary to a FunctionDecl found by lookup. The lookup is performed 111362e747f6SGabor Marton // by the given Name, and in the global scope. The summary will be attached 111462e747f6SGabor Marton // to the found FunctionDecl only if the signatures match. 11153ff220deSGabor Marton // 11163ff220deSGabor Marton // Returns true if the summary has been added, false otherwise. 111711d2e63aSGabor Marton bool operator()(StringRef Name, Signature Sign, Summary Sum) { 111811d2e63aSGabor Marton if (Sign.isInvalid()) 1119a787a4edSGabor Marton return false; 112062e747f6SGabor Marton IdentifierInfo &II = ACtx.Idents.get(Name); 112162e747f6SGabor Marton auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); 11220cb7e7caSVassil Vassilev if (LookupRes.empty()) 11233ff220deSGabor Marton return false; 112462e747f6SGabor Marton for (Decl *D : LookupRes) { 112562e747f6SGabor Marton if (auto *FD = dyn_cast<FunctionDecl>(D)) { 112611d2e63aSGabor Marton if (Sum.matchesAndSet(Sign, FD)) { 112711d2e63aSGabor Marton auto Res = Map.insert({FD->getCanonicalDecl(), Sum}); 112862e747f6SGabor Marton assert(Res.second && "Function already has a summary set!"); 112962e747f6SGabor Marton (void)Res; 1130ff4492c8SGabor Marton if (DisplayLoadedSummaries) { 1131ff4492c8SGabor Marton llvm::errs() << "Loaded summary for: "; 1132ff4492c8SGabor Marton FD->print(llvm::errs()); 1133ff4492c8SGabor Marton llvm::errs() << "\n"; 1134ff4492c8SGabor Marton } 11353ff220deSGabor Marton return true; 113662e747f6SGabor Marton } 113762e747f6SGabor Marton } 113862e747f6SGabor Marton } 11393ff220deSGabor Marton return false; 11403ff220deSGabor Marton } 1141fe0972d3SGabor Marton // Add the same summary for different names with the Signature explicitly 1142fe0972d3SGabor Marton // given. 1143fe0972d3SGabor Marton void operator()(std::vector<StringRef> Names, Signature Sign, Summary Sum) { 1144fe0972d3SGabor Marton for (StringRef Name : Names) 1145fe0972d3SGabor Marton operator()(Name, Sign, Sum); 1146fe0972d3SGabor Marton } 1147ff4492c8SGabor Marton } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries); 114862e747f6SGabor Marton 1149c6b8484eSGabor Marton // Below are helpers functions to create the summaries. 1150c6b8484eSGabor Marton auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind, 1151c6b8484eSGabor Marton IntRangeVector Ranges) { 1152c6b8484eSGabor Marton return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges); 1153f5086b38SGabor Marton }; 115441928c97SGabor Marton auto BufferSize = [](auto... Args) { 115541928c97SGabor Marton return std::make_shared<BufferSizeConstraint>(Args...); 1156bd03ef19SGabor Marton }; 1157c6b8484eSGabor Marton struct { 1158c6b8484eSGabor Marton auto operator()(RangeKind Kind, IntRangeVector Ranges) { 1159c6b8484eSGabor Marton return std::make_shared<RangeConstraint>(Ret, Kind, Ranges); 1160c6b8484eSGabor Marton } 1161c6b8484eSGabor Marton auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) { 1162c6b8484eSGabor Marton return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN); 1163c6b8484eSGabor Marton } 1164c6b8484eSGabor Marton } ReturnValueCondition; 1165a787a4edSGabor Marton struct { 1166a787a4edSGabor Marton auto operator()(RangeInt b, RangeInt e) { 1167f5086b38SGabor Marton return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}}; 1168a787a4edSGabor Marton } 1169a787a4edSGabor Marton auto operator()(RangeInt b, Optional<RangeInt> e) { 1170a787a4edSGabor Marton if (e) 1171a787a4edSGabor Marton return IntRangeVector{std::pair<RangeInt, RangeInt>{b, *e}}; 1172a787a4edSGabor Marton return IntRangeVector{}; 1173a787a4edSGabor Marton } 1174d63a945aSGabor Marton auto operator()(std::pair<RangeInt, RangeInt> i0, 1175d63a945aSGabor Marton std::pair<RangeInt, Optional<RangeInt>> i1) { 1176d63a945aSGabor Marton if (i1.second) 1177d63a945aSGabor Marton return IntRangeVector{i0, {i1.first, *(i1.second)}}; 1178d63a945aSGabor Marton return IntRangeVector{i0}; 1179d63a945aSGabor Marton } 1180a787a4edSGabor Marton } Range; 1181f5086b38SGabor Marton auto SingleValue = [](RangeInt v) { 1182f5086b38SGabor Marton return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}}; 1183f5086b38SGabor Marton }; 1184c6b8484eSGabor Marton auto LessThanOrEq = BO_LE; 1185ededa65dSGabor Marton auto NotNull = [&](ArgNo ArgN) { 1186ededa65dSGabor Marton return std::make_shared<NotNullConstraint>(ArgN); 1187ededa65dSGabor Marton }; 1188f5086b38SGabor Marton 1189a787a4edSGabor Marton Optional<QualType> FileTy = lookupTy("FILE"); 1190a787a4edSGabor Marton Optional<QualType> FilePtrTy = getPointerTy(FileTy); 1191a787a4edSGabor Marton Optional<QualType> FilePtrRestrictTy = getRestrictTy(FilePtrTy); 1192634258b8SGabor Marton 1193a787a4edSGabor Marton // We are finally ready to define specifications for all supported functions. 1194a787a4edSGabor Marton // 1195a787a4edSGabor Marton // Argument ranges should always cover all variants. If return value 1196a787a4edSGabor Marton // is completely unknown, omit it from the respective range set. 1197a787a4edSGabor Marton // 1198a787a4edSGabor Marton // Every item in the list of range sets represents a particular 1199a787a4edSGabor Marton // execution path the analyzer would need to explore once 1200a787a4edSGabor Marton // the call is modeled - a new program state is constructed 1201a787a4edSGabor Marton // for every range set, and each range line in the range set 1202a787a4edSGabor Marton // corresponds to a specific constraint within this state. 1203a787a4edSGabor Marton 1204bba497fbSArtem Dergachev // The isascii() family of functions. 120594061df6SGabor Marton // The behavior is undefined if the value of the argument is not 120694061df6SGabor Marton // representable as unsigned char or is not equal to EOF. See e.g. C99 120794061df6SGabor Marton // 7.4.1.2 The isalpha function (p: 181-182). 120862e747f6SGabor Marton addToFunctionSummaryMap( 120911d2e63aSGabor Marton "isalnum", Signature(ArgTypes{IntTy}, RetType{IntTy}), 121011d2e63aSGabor Marton Summary(EvalCallAsPure) 1211f5086b38SGabor Marton // Boils down to isupper() or islower() or isdigit(). 121262e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, 1213f5086b38SGabor Marton {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}), 1214f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1215f5086b38SGabor Marton // The locale-specific range. 1216bba497fbSArtem Dergachev // No post-condition. We are completely unaware of 1217bba497fbSArtem Dergachev // locale-specific return values. 121862e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 121962e747f6SGabor Marton .Case( 122062e747f6SGabor Marton {ArgumentCondition( 122162e747f6SGabor Marton 0U, OutOfRange, 122262e747f6SGabor Marton {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), 122394061df6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))}) 122494061df6SGabor Marton .ArgConstraint(ArgumentCondition( 122562e747f6SGabor Marton 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); 122662e747f6SGabor Marton addToFunctionSummaryMap( 122711d2e63aSGabor Marton "isalpha", Signature(ArgTypes{IntTy}, RetType{IntTy}), 122811d2e63aSGabor Marton Summary(EvalCallAsPure) 122962e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}), 1230f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1231f5086b38SGabor Marton // The locale-specific range. 123262e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 1233536456a7SGabor Marton .Case({ArgumentCondition( 1234536456a7SGabor Marton 0U, OutOfRange, 12350eba5dc8SArtem Dergachev {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), 123662e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 123762e747f6SGabor Marton addToFunctionSummaryMap( 123811d2e63aSGabor Marton "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}), 123911d2e63aSGabor Marton Summary(EvalCallAsPure) 1240f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), 1241f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1242f5086b38SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)), 124362e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 124462e747f6SGabor Marton addToFunctionSummaryMap( 124511d2e63aSGabor Marton "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}), 124611d2e63aSGabor Marton Summary(EvalCallAsPure) 124762e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}), 1248f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 124962e747f6SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}), 125062e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 125162e747f6SGabor Marton addToFunctionSummaryMap( 125211d2e63aSGabor Marton "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}), 125311d2e63aSGabor Marton Summary(EvalCallAsPure) 125462e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}), 1255f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 125662e747f6SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}), 125762e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 125862e747f6SGabor Marton addToFunctionSummaryMap( 125911d2e63aSGabor Marton "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}), 126011d2e63aSGabor Marton Summary(EvalCallAsPure) 1261f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')), 1262f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1263f5086b38SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')), 126462e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 126562e747f6SGabor Marton addToFunctionSummaryMap( 126611d2e63aSGabor Marton "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}), 126711d2e63aSGabor Marton Summary(EvalCallAsPure) 1268f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)), 1269f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1270f5086b38SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)), 127162e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 127262e747f6SGabor Marton addToFunctionSummaryMap( 127311d2e63aSGabor Marton "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}), 127411d2e63aSGabor Marton Summary(EvalCallAsPure) 1275f5086b38SGabor Marton // Is certainly lowercase. 1276f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')), 1277f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1278f5086b38SGabor Marton // Is ascii but not lowercase. 1279f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), 1280f5086b38SGabor Marton ArgumentCondition(0U, OutOfRange, Range('a', 'z')), 1281f5086b38SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))}) 1282f5086b38SGabor Marton // The locale-specific range. 128362e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 1284f5086b38SGabor Marton // Is not an unsigned char. 128562e747f6SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)), 128662e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 128762e747f6SGabor Marton addToFunctionSummaryMap( 128811d2e63aSGabor Marton "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}), 128911d2e63aSGabor Marton Summary(EvalCallAsPure) 1290f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)), 1291f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1292f5086b38SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)), 129362e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 129462e747f6SGabor Marton addToFunctionSummaryMap( 129511d2e63aSGabor Marton "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}), 129611d2e63aSGabor Marton Summary(EvalCallAsPure) 1297f5086b38SGabor Marton .Case({ArgumentCondition( 1298f5086b38SGabor Marton 0U, WithinRange, 1299f5086b38SGabor Marton {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), 1300f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1301f5086b38SGabor Marton .Case({ArgumentCondition( 1302f5086b38SGabor Marton 0U, OutOfRange, 1303f5086b38SGabor Marton {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), 130462e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 130562e747f6SGabor Marton addToFunctionSummaryMap( 130611d2e63aSGabor Marton "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}), 130711d2e63aSGabor Marton Summary(EvalCallAsPure) 1308f5086b38SGabor Marton // Space, '\f', '\n', '\r', '\t', '\v'. 130962e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}), 1310f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1311f5086b38SGabor Marton // The locale-specific range. 131262e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 131362e747f6SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, 13140eba5dc8SArtem Dergachev {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}), 131562e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 131662e747f6SGabor Marton addToFunctionSummaryMap( 131711d2e63aSGabor Marton "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}), 131811d2e63aSGabor Marton Summary(EvalCallAsPure) 1319f5086b38SGabor Marton // Is certainly uppercase. 1320f5086b38SGabor Marton .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')), 1321f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 1322f5086b38SGabor Marton // The locale-specific range. 132362e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 1324f5086b38SGabor Marton // Other. 1325f5086b38SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, 13260eba5dc8SArtem Dergachev {{'A', 'Z'}, {128, UCharRangeMax}}), 132762e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 132862e747f6SGabor Marton addToFunctionSummaryMap( 132911d2e63aSGabor Marton "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}), 133011d2e63aSGabor Marton Summary(EvalCallAsPure) 133162e747f6SGabor Marton .Case({ArgumentCondition(0U, WithinRange, 1332f5086b38SGabor Marton {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), 1333f5086b38SGabor Marton ReturnValueCondition(OutOfRange, SingleValue(0))}) 133462e747f6SGabor Marton .Case({ArgumentCondition(0U, OutOfRange, 1335f5086b38SGabor Marton {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), 133662e747f6SGabor Marton ReturnValueCondition(WithinRange, SingleValue(0))})); 133725bbe234SZurab Tsinadze addToFunctionSummaryMap( 133811d2e63aSGabor Marton "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}), 133911d2e63aSGabor Marton Summary(EvalCallAsPure) 134025bbe234SZurab Tsinadze .ArgConstraint(ArgumentCondition( 134125bbe234SZurab Tsinadze 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); 134225bbe234SZurab Tsinadze addToFunctionSummaryMap( 134311d2e63aSGabor Marton "tolower", Signature(ArgTypes{IntTy}, RetType{IntTy}), 134411d2e63aSGabor Marton Summary(EvalCallAsPure) 134525bbe234SZurab Tsinadze .ArgConstraint(ArgumentCondition( 134625bbe234SZurab Tsinadze 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); 134725bbe234SZurab Tsinadze addToFunctionSummaryMap( 134811d2e63aSGabor Marton "toascii", Signature(ArgTypes{IntTy}, RetType{IntTy}), 134911d2e63aSGabor Marton Summary(EvalCallAsPure) 135025bbe234SZurab Tsinadze .ArgConstraint(ArgumentCondition( 135125bbe234SZurab Tsinadze 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); 1352bba497fbSArtem Dergachev 1353bba497fbSArtem Dergachev // The getc() family of functions that returns either a char or an EOF. 1354a012bc4cSGabor Marton addToFunctionSummaryMap( 1355a012bc4cSGabor Marton {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), 1356a012bc4cSGabor Marton Summary(NoEvalCall) 1357a012bc4cSGabor Marton .Case({ReturnValueCondition(WithinRange, 1358a012bc4cSGabor Marton {{EOFv, EOFv}, {0, UCharRangeMax}})})); 135962e747f6SGabor Marton addToFunctionSummaryMap( 136011d2e63aSGabor Marton "getchar", Signature(ArgTypes{}, RetType{IntTy}), 136111d2e63aSGabor Marton Summary(NoEvalCall) 136211d2e63aSGabor Marton .Case({ReturnValueCondition(WithinRange, 136311d2e63aSGabor Marton {{EOFv, EOFv}, {0, UCharRangeMax}})})); 1364bba497fbSArtem Dergachev 1365bba497fbSArtem Dergachev // read()-like functions that never return more than buffer size. 1366a012bc4cSGabor Marton auto FreadSummary = 1367a012bc4cSGabor Marton Summary(NoEvalCall) 1368b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 1369b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(0, SizeMax))}) 1370a012bc4cSGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1371a012bc4cSGabor Marton .ArgConstraint(NotNull(ArgNo(3))) 1372a012bc4cSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), 1373a012bc4cSGabor Marton /*BufSizeMultiplier=*/ArgNo(2))); 1374a012bc4cSGabor Marton 1375a012bc4cSGabor Marton // size_t fread(void *restrict ptr, size_t size, size_t nitems, 1376a012bc4cSGabor Marton // FILE *restrict stream); 1377a012bc4cSGabor Marton addToFunctionSummaryMap( 1378a012bc4cSGabor Marton "fread", 1379a012bc4cSGabor Marton Signature(ArgTypes{VoidPtrRestrictTy, SizeTy, SizeTy, FilePtrRestrictTy}, 1380a012bc4cSGabor Marton RetType{SizeTy}), 1381a012bc4cSGabor Marton FreadSummary); 1382a012bc4cSGabor Marton // size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, 1383a012bc4cSGabor Marton // FILE *restrict stream); 1384a012bc4cSGabor Marton addToFunctionSummaryMap("fwrite", 1385a012bc4cSGabor Marton Signature(ArgTypes{ConstVoidPtrRestrictTy, SizeTy, 1386a012bc4cSGabor Marton SizeTy, FilePtrRestrictTy}, 1387a012bc4cSGabor Marton RetType{SizeTy}), 1388a012bc4cSGabor Marton FreadSummary); 1389634258b8SGabor Marton 1390d63a945aSGabor Marton Optional<QualType> Ssize_tTy = lookupTy("ssize_t"); 1391d63a945aSGabor Marton Optional<RangeInt> Ssize_tMax = getMaxValue(Ssize_tTy); 1392d63a945aSGabor Marton 1393d63a945aSGabor Marton auto ReadSummary = 1394d63a945aSGabor Marton Summary(NoEvalCall) 1395d63a945aSGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 1396d63a945aSGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}); 1397d63a945aSGabor Marton 1398634258b8SGabor Marton // FIXME these are actually defined by POSIX and not by the C standard, we 1399634258b8SGabor Marton // should handle them together with the rest of the POSIX functions. 1400d63a945aSGabor Marton // ssize_t read(int fildes, void *buf, size_t nbyte); 1401d63a945aSGabor Marton addToFunctionSummaryMap( 1402d63a945aSGabor Marton "read", Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy}, RetType{Ssize_tTy}), 1403d63a945aSGabor Marton ReadSummary); 1404d63a945aSGabor Marton // ssize_t write(int fildes, const void *buf, size_t nbyte); 1405d63a945aSGabor Marton addToFunctionSummaryMap( 1406d63a945aSGabor Marton "write", 1407d63a945aSGabor Marton Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy}, RetType{Ssize_tTy}), 1408d63a945aSGabor Marton ReadSummary); 1409d63a945aSGabor Marton 1410d63a945aSGabor Marton auto GetLineSummary = 1411d63a945aSGabor Marton Summary(NoEvalCall) 1412d63a945aSGabor Marton .Case({ReturnValueCondition(WithinRange, 1413d63a945aSGabor Marton Range({-1, -1}, {1, Ssize_tMax}))}); 1414d63a945aSGabor Marton 1415d63a945aSGabor Marton QualType CharPtrPtrRestrictTy = getRestrictTy(getPointerTy(CharPtrTy)); 1416634258b8SGabor Marton 1417bba497fbSArtem Dergachev // getline()-like functions either fail or read at least the delimiter. 1418634258b8SGabor Marton // FIXME these are actually defined by POSIX and not by the C standard, we 1419634258b8SGabor Marton // should handle them together with the rest of the POSIX functions. 1420d63a945aSGabor Marton // ssize_t getline(char **restrict lineptr, size_t *restrict n, 1421d63a945aSGabor Marton // FILE *restrict stream); 1422d63a945aSGabor Marton addToFunctionSummaryMap( 1423d63a945aSGabor Marton "getline", 1424d63a945aSGabor Marton Signature( 1425d63a945aSGabor Marton ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, FilePtrRestrictTy}, 1426d63a945aSGabor Marton RetType{Ssize_tTy}), 1427d63a945aSGabor Marton GetLineSummary); 1428d63a945aSGabor Marton // ssize_t getdelim(char **restrict lineptr, size_t *restrict n, 1429d63a945aSGabor Marton // int delimiter, FILE *restrict stream); 1430d63a945aSGabor Marton addToFunctionSummaryMap( 1431d63a945aSGabor Marton "getdelim", 1432d63a945aSGabor Marton Signature(ArgTypes{CharPtrPtrRestrictTy, SizePtrRestrictTy, IntTy, 1433d63a945aSGabor Marton FilePtrRestrictTy}, 1434d63a945aSGabor Marton RetType{Ssize_tTy}), 1435d63a945aSGabor Marton GetLineSummary); 14361525232eSGabor Marton 1437*edde4efcSBalazs Benics { 1438*edde4efcSBalazs Benics Summary GetenvSummary = Summary(NoEvalCall) 1439*edde4efcSBalazs Benics .ArgConstraint(NotNull(ArgNo(0))) 1440*edde4efcSBalazs Benics .Case({NotNull(Ret)}); 1441*edde4efcSBalazs Benics // In untrusted environments the envvar might not exist. 1442*edde4efcSBalazs Benics if (!ShouldAssumeControlledEnvironment) 1443*edde4efcSBalazs Benics GetenvSummary.Case({NotNull(Ret)->negate()}); 1444*edde4efcSBalazs Benics 14457fc15030SBalazs Benics // char *getenv(const char *name); 14467fc15030SBalazs Benics addToFunctionSummaryMap( 14477fc15030SBalazs Benics "getenv", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}), 1448*edde4efcSBalazs Benics std::move(GetenvSummary)); 1449*edde4efcSBalazs Benics } 14507fc15030SBalazs Benics 1451db4d5f70SGabor Marton if (ModelPOSIX) { 1452db4d5f70SGabor Marton 1453db4d5f70SGabor Marton // long a64l(const char *str64); 1454db4d5f70SGabor Marton addToFunctionSummaryMap( 145511d2e63aSGabor Marton "a64l", Signature(ArgTypes{ConstCharPtrTy}, RetType{LongTy}), 145611d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1457db4d5f70SGabor Marton 1458db4d5f70SGabor Marton // char *l64a(long value); 145911d2e63aSGabor Marton addToFunctionSummaryMap("l64a", 146011d2e63aSGabor Marton Signature(ArgTypes{LongTy}, RetType{CharPtrTy}), 146111d2e63aSGabor Marton Summary(NoEvalCall) 146211d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 146311d2e63aSGabor Marton 0, WithinRange, Range(0, LongMax)))); 1464db4d5f70SGabor Marton 1465febe7503SGabor Marton const auto ReturnsZeroOrMinusOne = 1466febe7503SGabor Marton ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))}; 1467febe7503SGabor Marton const auto ReturnsFileDescriptor = 1468febe7503SGabor Marton ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))}; 1469febe7503SGabor Marton 1470db4d5f70SGabor Marton // int access(const char *pathname, int amode); 147111d2e63aSGabor Marton addToFunctionSummaryMap( 147211d2e63aSGabor Marton "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}), 1473febe7503SGabor Marton Summary(NoEvalCall) 1474febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1475febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1476db4d5f70SGabor Marton 1477db4d5f70SGabor Marton // int faccessat(int dirfd, const char *pathname, int mode, int flags); 1478db4d5f70SGabor Marton addToFunctionSummaryMap( 147911d2e63aSGabor Marton "faccessat", 148011d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy}, 148111d2e63aSGabor Marton RetType{IntTy}), 1482febe7503SGabor Marton Summary(NoEvalCall) 1483febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1484febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1485db4d5f70SGabor Marton 1486db4d5f70SGabor Marton // int dup(int fildes); 148711d2e63aSGabor Marton addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}), 148811d2e63aSGabor Marton Summary(NoEvalCall) 1489febe7503SGabor Marton .Case(ReturnsFileDescriptor) 149011d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 149111d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 1492db4d5f70SGabor Marton 1493db4d5f70SGabor Marton // int dup2(int fildes1, int filedes2); 1494db4d5f70SGabor Marton addToFunctionSummaryMap( 149511d2e63aSGabor Marton "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), 149611d2e63aSGabor Marton Summary(NoEvalCall) 1497febe7503SGabor Marton .Case(ReturnsFileDescriptor) 1498db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1499db4d5f70SGabor Marton .ArgConstraint( 1500db4d5f70SGabor Marton ArgumentCondition(1, WithinRange, Range(0, IntMax)))); 1501db4d5f70SGabor Marton 1502db4d5f70SGabor Marton // int fdatasync(int fildes); 150311d2e63aSGabor Marton addToFunctionSummaryMap("fdatasync", 150411d2e63aSGabor Marton Signature(ArgTypes{IntTy}, RetType{IntTy}), 150511d2e63aSGabor Marton Summary(NoEvalCall) 1506febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 150711d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 150811d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 1509db4d5f70SGabor Marton 1510db4d5f70SGabor Marton // int fnmatch(const char *pattern, const char *string, int flags); 1511db4d5f70SGabor Marton addToFunctionSummaryMap( 151211d2e63aSGabor Marton "fnmatch", 151311d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy}, 151411d2e63aSGabor Marton RetType{IntTy}), 151511d2e63aSGabor Marton Summary(EvalCallAsPure) 1516db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1517db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1518db4d5f70SGabor Marton 1519db4d5f70SGabor Marton // int fsync(int fildes); 152011d2e63aSGabor Marton addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}), 152111d2e63aSGabor Marton Summary(NoEvalCall) 1522febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 152311d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 152411d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 1525db4d5f70SGabor Marton 1526a787a4edSGabor Marton Optional<QualType> Off_tTy = lookupTy("off_t"); 1527db4d5f70SGabor Marton 1528db4d5f70SGabor Marton // int truncate(const char *path, off_t length); 1529a787a4edSGabor Marton addToFunctionSummaryMap( 1530a787a4edSGabor Marton "truncate", 153111d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}), 1532febe7503SGabor Marton Summary(NoEvalCall) 1533febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1534febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1535db4d5f70SGabor Marton 1536db4d5f70SGabor Marton // int symlink(const char *oldpath, const char *newpath); 153711d2e63aSGabor Marton addToFunctionSummaryMap( 153811d2e63aSGabor Marton "symlink", 153911d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}), 154011d2e63aSGabor Marton Summary(NoEvalCall) 1541febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1542db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1543db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1544db4d5f70SGabor Marton 1545db4d5f70SGabor Marton // int symlinkat(const char *oldpath, int newdirfd, const char *newpath); 1546db4d5f70SGabor Marton addToFunctionSummaryMap( 1547db4d5f70SGabor Marton "symlinkat", 154811d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy}, 154911d2e63aSGabor Marton RetType{IntTy}), 155011d2e63aSGabor Marton Summary(NoEvalCall) 1551febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1552db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1553db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax))) 1554db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(2)))); 1555db4d5f70SGabor Marton 1556db4d5f70SGabor Marton // int lockf(int fd, int cmd, off_t len); 1557db4d5f70SGabor Marton addToFunctionSummaryMap( 155811d2e63aSGabor Marton "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}), 155911d2e63aSGabor Marton Summary(NoEvalCall) 1560febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1561db4d5f70SGabor Marton .ArgConstraint( 1562db4d5f70SGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1563db4d5f70SGabor Marton 1564a787a4edSGabor Marton Optional<QualType> Mode_tTy = lookupTy("mode_t"); 1565db4d5f70SGabor Marton 1566db4d5f70SGabor Marton // int creat(const char *pathname, mode_t mode); 156711d2e63aSGabor Marton addToFunctionSummaryMap( 156811d2e63aSGabor Marton "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1569febe7503SGabor Marton Summary(NoEvalCall) 1570febe7503SGabor Marton .Case(ReturnsFileDescriptor) 1571febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1572db4d5f70SGabor Marton 1573db4d5f70SGabor Marton // unsigned int sleep(unsigned int seconds); 1574db4d5f70SGabor Marton addToFunctionSummaryMap( 157511d2e63aSGabor Marton "sleep", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}), 157611d2e63aSGabor Marton Summary(NoEvalCall) 1577db4d5f70SGabor Marton .ArgConstraint( 1578db4d5f70SGabor Marton ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax)))); 1579db4d5f70SGabor Marton 1580a787a4edSGabor Marton Optional<QualType> DirTy = lookupTy("DIR"); 1581a787a4edSGabor Marton Optional<QualType> DirPtrTy = getPointerTy(DirTy); 1582db4d5f70SGabor Marton 1583db4d5f70SGabor Marton // int dirfd(DIR *dirp); 1584febe7503SGabor Marton addToFunctionSummaryMap("dirfd", 1585febe7503SGabor Marton Signature(ArgTypes{DirPtrTy}, RetType{IntTy}), 1586febe7503SGabor Marton Summary(NoEvalCall) 1587febe7503SGabor Marton .Case(ReturnsFileDescriptor) 1588febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1589db4d5f70SGabor Marton 1590db4d5f70SGabor Marton // unsigned int alarm(unsigned int seconds); 1591db4d5f70SGabor Marton addToFunctionSummaryMap( 159211d2e63aSGabor Marton "alarm", Signature(ArgTypes{UnsignedIntTy}, RetType{UnsignedIntTy}), 159311d2e63aSGabor Marton Summary(NoEvalCall) 1594db4d5f70SGabor Marton .ArgConstraint( 1595db4d5f70SGabor Marton ArgumentCondition(0, WithinRange, Range(0, UnsignedIntMax)))); 1596db4d5f70SGabor Marton 1597db4d5f70SGabor Marton // int closedir(DIR *dir); 1598febe7503SGabor Marton addToFunctionSummaryMap("closedir", 1599febe7503SGabor Marton Signature(ArgTypes{DirPtrTy}, RetType{IntTy}), 1600febe7503SGabor Marton Summary(NoEvalCall) 1601febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1602febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1603db4d5f70SGabor Marton 1604db4d5f70SGabor Marton // char *strdup(const char *s); 160511d2e63aSGabor Marton addToFunctionSummaryMap( 160611d2e63aSGabor Marton "strdup", Signature(ArgTypes{ConstCharPtrTy}, RetType{CharPtrTy}), 160711d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1608db4d5f70SGabor Marton 1609db4d5f70SGabor Marton // char *strndup(const char *s, size_t n); 1610db4d5f70SGabor Marton addToFunctionSummaryMap( 161111d2e63aSGabor Marton "strndup", 161211d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, SizeTy}, RetType{CharPtrTy}), 161311d2e63aSGabor Marton Summary(NoEvalCall) 1614db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 161511d2e63aSGabor Marton .ArgConstraint( 161611d2e63aSGabor Marton ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); 1617db4d5f70SGabor Marton 1618db4d5f70SGabor Marton // wchar_t *wcsdup(const wchar_t *s); 161911d2e63aSGabor Marton addToFunctionSummaryMap( 162011d2e63aSGabor Marton "wcsdup", Signature(ArgTypes{ConstWchar_tPtrTy}, RetType{Wchar_tPtrTy}), 162111d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1622db4d5f70SGabor Marton 1623db4d5f70SGabor Marton // int mkstemp(char *template); 1624febe7503SGabor Marton addToFunctionSummaryMap("mkstemp", 1625febe7503SGabor Marton Signature(ArgTypes{CharPtrTy}, RetType{IntTy}), 1626febe7503SGabor Marton Summary(NoEvalCall) 1627febe7503SGabor Marton .Case(ReturnsFileDescriptor) 1628febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1629db4d5f70SGabor Marton 1630db4d5f70SGabor Marton // char *mkdtemp(char *template); 1631db4d5f70SGabor Marton addToFunctionSummaryMap( 163211d2e63aSGabor Marton "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}), 163311d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1634db4d5f70SGabor Marton 1635db4d5f70SGabor Marton // char *getcwd(char *buf, size_t size); 1636db4d5f70SGabor Marton addToFunctionSummaryMap( 163711d2e63aSGabor Marton "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}), 163811d2e63aSGabor Marton Summary(NoEvalCall) 1639db4d5f70SGabor Marton .ArgConstraint( 1640db4d5f70SGabor Marton ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); 1641db4d5f70SGabor Marton 1642db4d5f70SGabor Marton // int mkdir(const char *pathname, mode_t mode); 164311d2e63aSGabor Marton addToFunctionSummaryMap( 164411d2e63aSGabor Marton "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1645febe7503SGabor Marton Summary(NoEvalCall) 1646febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1647febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1648db4d5f70SGabor Marton 1649db4d5f70SGabor Marton // int mkdirat(int dirfd, const char *pathname, mode_t mode); 165011d2e63aSGabor Marton addToFunctionSummaryMap( 165111d2e63aSGabor Marton "mkdirat", 165211d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1653febe7503SGabor Marton Summary(NoEvalCall) 1654febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1655febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1656db4d5f70SGabor Marton 1657a787a4edSGabor Marton Optional<QualType> Dev_tTy = lookupTy("dev_t"); 1658db4d5f70SGabor Marton 1659db4d5f70SGabor Marton // int mknod(const char *pathname, mode_t mode, dev_t dev); 166011d2e63aSGabor Marton addToFunctionSummaryMap( 166111d2e63aSGabor Marton "mknod", 166211d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}), 1663febe7503SGabor Marton Summary(NoEvalCall) 1664febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1665febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1666db4d5f70SGabor Marton 1667db4d5f70SGabor Marton // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev); 1668a787a4edSGabor Marton addToFunctionSummaryMap( 166911d2e63aSGabor Marton "mknodat", 167011d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy}, 167111d2e63aSGabor Marton RetType{IntTy}), 1672febe7503SGabor Marton Summary(NoEvalCall) 1673febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1674febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1675db4d5f70SGabor Marton 1676db4d5f70SGabor Marton // int chmod(const char *path, mode_t mode); 167711d2e63aSGabor Marton addToFunctionSummaryMap( 167811d2e63aSGabor Marton "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1679febe7503SGabor Marton Summary(NoEvalCall) 1680febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1681febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1682db4d5f70SGabor Marton 1683db4d5f70SGabor Marton // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); 1684db4d5f70SGabor Marton addToFunctionSummaryMap( 1685a787a4edSGabor Marton "fchmodat", 168611d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy}, 168711d2e63aSGabor Marton RetType{IntTy}), 168811d2e63aSGabor Marton Summary(NoEvalCall) 1689febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1690a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1691db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1692db4d5f70SGabor Marton 1693db4d5f70SGabor Marton // int fchmod(int fildes, mode_t mode); 1694db4d5f70SGabor Marton addToFunctionSummaryMap( 169511d2e63aSGabor Marton "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}), 169611d2e63aSGabor Marton Summary(NoEvalCall) 1697febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1698db4d5f70SGabor Marton .ArgConstraint( 1699db4d5f70SGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1700db4d5f70SGabor Marton 1701a787a4edSGabor Marton Optional<QualType> Uid_tTy = lookupTy("uid_t"); 1702a787a4edSGabor Marton Optional<QualType> Gid_tTy = lookupTy("gid_t"); 1703db4d5f70SGabor Marton 1704db4d5f70SGabor Marton // int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, 1705db4d5f70SGabor Marton // int flags); 1706db4d5f70SGabor Marton addToFunctionSummaryMap( 1707db4d5f70SGabor Marton "fchownat", 170811d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy}, 170911d2e63aSGabor Marton RetType{IntTy}), 171011d2e63aSGabor Marton Summary(NoEvalCall) 1711febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1712a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1713db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1714db4d5f70SGabor Marton 1715db4d5f70SGabor Marton // int chown(const char *path, uid_t owner, gid_t group); 171611d2e63aSGabor Marton addToFunctionSummaryMap( 171711d2e63aSGabor Marton "chown", 171811d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 1719febe7503SGabor Marton Summary(NoEvalCall) 1720febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1721febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1722db4d5f70SGabor Marton 1723db4d5f70SGabor Marton // int lchown(const char *path, uid_t owner, gid_t group); 172411d2e63aSGabor Marton addToFunctionSummaryMap( 172511d2e63aSGabor Marton "lchown", 172611d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 1727febe7503SGabor Marton Summary(NoEvalCall) 1728febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1729febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1730db4d5f70SGabor Marton 1731db4d5f70SGabor Marton // int fchown(int fildes, uid_t owner, gid_t group); 1732db4d5f70SGabor Marton addToFunctionSummaryMap( 173311d2e63aSGabor Marton "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 173411d2e63aSGabor Marton Summary(NoEvalCall) 1735febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1736a787a4edSGabor Marton .ArgConstraint( 1737a787a4edSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1738db4d5f70SGabor Marton 1739db4d5f70SGabor Marton // int rmdir(const char *pathname); 1740febe7503SGabor Marton addToFunctionSummaryMap("rmdir", 1741febe7503SGabor Marton Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 1742febe7503SGabor Marton Summary(NoEvalCall) 1743febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1744febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1745db4d5f70SGabor Marton 1746db4d5f70SGabor Marton // int chdir(const char *path); 1747febe7503SGabor Marton addToFunctionSummaryMap("chdir", 1748febe7503SGabor Marton Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 1749febe7503SGabor Marton Summary(NoEvalCall) 1750febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1751febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1752db4d5f70SGabor Marton 1753db4d5f70SGabor Marton // int link(const char *oldpath, const char *newpath); 175411d2e63aSGabor Marton addToFunctionSummaryMap( 175511d2e63aSGabor Marton "link", 175611d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}), 175711d2e63aSGabor Marton Summary(NoEvalCall) 1758febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1759db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1760db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1761db4d5f70SGabor Marton 1762db4d5f70SGabor Marton // int linkat(int fd1, const char *path1, int fd2, const char *path2, 1763db4d5f70SGabor Marton // int flag); 1764db4d5f70SGabor Marton addToFunctionSummaryMap( 1765db4d5f70SGabor Marton "linkat", 176611d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy}, 176711d2e63aSGabor Marton RetType{IntTy}), 176811d2e63aSGabor Marton Summary(NoEvalCall) 1769febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1770db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1771db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 1772db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax))) 1773db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(3)))); 1774db4d5f70SGabor Marton 1775db4d5f70SGabor Marton // int unlink(const char *pathname); 1776febe7503SGabor Marton addToFunctionSummaryMap("unlink", 1777febe7503SGabor Marton Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 1778febe7503SGabor Marton Summary(NoEvalCall) 1779febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1780febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1781db4d5f70SGabor Marton 1782db4d5f70SGabor Marton // int unlinkat(int fd, const char *path, int flag); 1783db4d5f70SGabor Marton addToFunctionSummaryMap( 1784db4d5f70SGabor Marton "unlinkat", 178511d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}), 178611d2e63aSGabor Marton Summary(NoEvalCall) 1787febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1788db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1789db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1790db4d5f70SGabor Marton 1791a787a4edSGabor Marton Optional<QualType> StructStatTy = lookupTy("stat"); 1792a787a4edSGabor Marton Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy); 1793a787a4edSGabor Marton Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy); 1794db4d5f70SGabor Marton 1795db4d5f70SGabor Marton // int fstat(int fd, struct stat *statbuf); 1796db4d5f70SGabor Marton addToFunctionSummaryMap( 179711d2e63aSGabor Marton "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}), 179811d2e63aSGabor Marton Summary(NoEvalCall) 1799febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1800a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1801db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1802db4d5f70SGabor Marton 1803db4d5f70SGabor Marton // int stat(const char *restrict path, struct stat *restrict buf); 180411d2e63aSGabor Marton addToFunctionSummaryMap( 180511d2e63aSGabor Marton "stat", 180611d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy}, 180711d2e63aSGabor Marton RetType{IntTy}), 180811d2e63aSGabor Marton Summary(NoEvalCall) 1809febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1810db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1811db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1812db4d5f70SGabor Marton 1813db4d5f70SGabor Marton // int lstat(const char *restrict path, struct stat *restrict buf); 181411d2e63aSGabor Marton addToFunctionSummaryMap( 181511d2e63aSGabor Marton "lstat", 181611d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy}, 181711d2e63aSGabor Marton RetType{IntTy}), 181811d2e63aSGabor Marton Summary(NoEvalCall) 1819febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1820db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1821db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1822db4d5f70SGabor Marton 1823db4d5f70SGabor Marton // int fstatat(int fd, const char *restrict path, 1824db4d5f70SGabor Marton // struct stat *restrict buf, int flag); 1825db4d5f70SGabor Marton addToFunctionSummaryMap( 1826a787a4edSGabor Marton "fstatat", 182711d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy, 182811d2e63aSGabor Marton StructStatPtrRestrictTy, IntTy}, 182911d2e63aSGabor Marton RetType{IntTy}), 183011d2e63aSGabor Marton Summary(NoEvalCall) 1831febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1832a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1833db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 1834db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(2)))); 1835db4d5f70SGabor Marton 1836db4d5f70SGabor Marton // DIR *opendir(const char *name); 183711d2e63aSGabor Marton addToFunctionSummaryMap( 183811d2e63aSGabor Marton "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}), 183911d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1840db4d5f70SGabor Marton 1841db4d5f70SGabor Marton // DIR *fdopendir(int fd); 184211d2e63aSGabor Marton addToFunctionSummaryMap("fdopendir", 184311d2e63aSGabor Marton Signature(ArgTypes{IntTy}, RetType{DirPtrTy}), 184411d2e63aSGabor Marton Summary(NoEvalCall) 184511d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 184611d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 1847db4d5f70SGabor Marton 1848db4d5f70SGabor Marton // int isatty(int fildes); 1849febe7503SGabor Marton addToFunctionSummaryMap( 1850febe7503SGabor Marton "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}), 185111d2e63aSGabor Marton Summary(NoEvalCall) 1852febe7503SGabor Marton .Case({ReturnValueCondition(WithinRange, Range(0, 1))}) 1853febe7503SGabor Marton .ArgConstraint( 1854febe7503SGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1855db4d5f70SGabor Marton 1856db4d5f70SGabor Marton // FILE *popen(const char *command, const char *type); 185711d2e63aSGabor Marton addToFunctionSummaryMap( 185811d2e63aSGabor Marton "popen", 185911d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}), 186011d2e63aSGabor Marton Summary(NoEvalCall) 1861db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1862db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1863db4d5f70SGabor Marton 1864db4d5f70SGabor Marton // int pclose(FILE *stream); 1865db4d5f70SGabor Marton addToFunctionSummaryMap( 186611d2e63aSGabor Marton "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), 186711d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1868db4d5f70SGabor Marton 1869db4d5f70SGabor Marton // int close(int fildes); 187011d2e63aSGabor Marton addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}), 187111d2e63aSGabor Marton Summary(NoEvalCall) 1872febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 187311d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 1874d14c6316SGabor Marton 0, WithinRange, Range(-1, IntMax)))); 1875db4d5f70SGabor Marton 1876db4d5f70SGabor Marton // long fpathconf(int fildes, int name); 187711d2e63aSGabor Marton addToFunctionSummaryMap("fpathconf", 187811d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}), 187911d2e63aSGabor Marton Summary(NoEvalCall) 188011d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 188111d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 1882db4d5f70SGabor Marton 1883db4d5f70SGabor Marton // long pathconf(const char *path, int name); 188411d2e63aSGabor Marton addToFunctionSummaryMap( 188511d2e63aSGabor Marton "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}), 188611d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1887db4d5f70SGabor Marton 1888db4d5f70SGabor Marton // FILE *fdopen(int fd, const char *mode); 1889db4d5f70SGabor Marton addToFunctionSummaryMap( 1890a787a4edSGabor Marton "fdopen", 189111d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}), 189211d2e63aSGabor Marton Summary(NoEvalCall) 1893a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1894db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 1895db4d5f70SGabor Marton 1896db4d5f70SGabor Marton // void rewinddir(DIR *dir); 1897db4d5f70SGabor Marton addToFunctionSummaryMap( 189811d2e63aSGabor Marton "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}), 189911d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1900db4d5f70SGabor Marton 1901db4d5f70SGabor Marton // void seekdir(DIR *dirp, long loc); 190211d2e63aSGabor Marton addToFunctionSummaryMap( 190311d2e63aSGabor Marton "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}), 190411d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1905db4d5f70SGabor Marton 1906db4d5f70SGabor Marton // int rand_r(unsigned int *seedp); 190711d2e63aSGabor Marton addToFunctionSummaryMap( 190811d2e63aSGabor Marton "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}), 190911d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1910db4d5f70SGabor Marton 1911db4d5f70SGabor Marton // int fileno(FILE *stream); 1912febe7503SGabor Marton addToFunctionSummaryMap("fileno", 1913febe7503SGabor Marton Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), 1914febe7503SGabor Marton Summary(NoEvalCall) 1915febe7503SGabor Marton .Case(ReturnsFileDescriptor) 1916febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1917db4d5f70SGabor Marton 1918db4d5f70SGabor Marton // int fseeko(FILE *stream, off_t offset, int whence); 1919a787a4edSGabor Marton addToFunctionSummaryMap( 1920a787a4edSGabor Marton "fseeko", 192111d2e63aSGabor Marton Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}), 1922febe7503SGabor Marton Summary(NoEvalCall) 1923febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1924febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1925db4d5f70SGabor Marton 1926db4d5f70SGabor Marton // off_t ftello(FILE *stream); 1927db4d5f70SGabor Marton addToFunctionSummaryMap( 192811d2e63aSGabor Marton "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}), 192911d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 1930db4d5f70SGabor Marton 1931db4d5f70SGabor Marton // void *mmap(void *addr, size_t length, int prot, int flags, int fd, 1932db4d5f70SGabor Marton // off_t offset); 1933db4d5f70SGabor Marton addToFunctionSummaryMap( 1934db4d5f70SGabor Marton "mmap", 193511d2e63aSGabor Marton Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy}, 193611d2e63aSGabor Marton RetType{VoidPtrTy}), 193711d2e63aSGabor Marton Summary(NoEvalCall) 1938a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) 1939db4d5f70SGabor Marton .ArgConstraint( 1940d14c6316SGabor Marton ArgumentCondition(4, WithinRange, Range(-1, IntMax)))); 1941db4d5f70SGabor Marton 1942a787a4edSGabor Marton Optional<QualType> Off64_tTy = lookupTy("off64_t"); 1943db4d5f70SGabor Marton // void *mmap64(void *addr, size_t length, int prot, int flags, int fd, 1944db4d5f70SGabor Marton // off64_t offset); 1945db4d5f70SGabor Marton addToFunctionSummaryMap( 1946db4d5f70SGabor Marton "mmap64", 194711d2e63aSGabor Marton Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy}, 194811d2e63aSGabor Marton RetType{VoidPtrTy}), 194911d2e63aSGabor Marton Summary(NoEvalCall) 1950a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) 1951db4d5f70SGabor Marton .ArgConstraint( 1952d14c6316SGabor Marton ArgumentCondition(4, WithinRange, Range(-1, IntMax)))); 1953db4d5f70SGabor Marton 1954db4d5f70SGabor Marton // int pipe(int fildes[2]); 1955febe7503SGabor Marton addToFunctionSummaryMap("pipe", 1956febe7503SGabor Marton Signature(ArgTypes{IntPtrTy}, RetType{IntTy}), 1957febe7503SGabor Marton Summary(NoEvalCall) 1958febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 1959febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 1960db4d5f70SGabor Marton 1961db4d5f70SGabor Marton // off_t lseek(int fildes, off_t offset, int whence); 1962db4d5f70SGabor Marton addToFunctionSummaryMap( 196311d2e63aSGabor Marton "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}), 196411d2e63aSGabor Marton Summary(NoEvalCall) 1965a787a4edSGabor Marton .ArgConstraint( 1966a787a4edSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1967db4d5f70SGabor Marton 1968db4d5f70SGabor Marton // ssize_t readlink(const char *restrict path, char *restrict buf, 1969db4d5f70SGabor Marton // size_t bufsize); 1970db4d5f70SGabor Marton addToFunctionSummaryMap( 1971db4d5f70SGabor Marton "readlink", 197211d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, 197311d2e63aSGabor Marton RetType{Ssize_tTy}), 197411d2e63aSGabor Marton Summary(NoEvalCall) 1975b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 1976b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 1977db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 1978db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 1979db4d5f70SGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 1980db4d5f70SGabor Marton /*BufSize=*/ArgNo(2))) 1981db4d5f70SGabor Marton .ArgConstraint( 1982db4d5f70SGabor Marton ArgumentCondition(2, WithinRange, Range(0, SizeMax)))); 1983db4d5f70SGabor Marton 1984db4d5f70SGabor Marton // ssize_t readlinkat(int fd, const char *restrict path, 1985db4d5f70SGabor Marton // char *restrict buf, size_t bufsize); 1986db4d5f70SGabor Marton addToFunctionSummaryMap( 1987a787a4edSGabor Marton "readlinkat", 198811d2e63aSGabor Marton Signature( 1989a787a4edSGabor Marton ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, 199011d2e63aSGabor Marton RetType{Ssize_tTy}), 199111d2e63aSGabor Marton Summary(NoEvalCall) 1992b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)), 1993b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 1994a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1995db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 1996db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(2))) 1997db4d5f70SGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2), 1998db4d5f70SGabor Marton /*BufSize=*/ArgNo(3))) 1999a787a4edSGabor Marton .ArgConstraint( 2000a787a4edSGabor Marton ArgumentCondition(3, WithinRange, Range(0, SizeMax)))); 2001db4d5f70SGabor Marton 2002db4d5f70SGabor Marton // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char 2003db4d5f70SGabor Marton // *newpath); 200411d2e63aSGabor Marton addToFunctionSummaryMap( 200511d2e63aSGabor Marton "renameat", 200611d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy}, 200711d2e63aSGabor Marton RetType{IntTy}), 200811d2e63aSGabor Marton Summary(NoEvalCall) 2009febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2010db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 2011db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(3)))); 2012db4d5f70SGabor Marton 2013db4d5f70SGabor Marton // char *realpath(const char *restrict file_name, 2014db4d5f70SGabor Marton // char *restrict resolved_name); 2015db4d5f70SGabor Marton addToFunctionSummaryMap( 201611d2e63aSGabor Marton "realpath", 201711d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy}, 201811d2e63aSGabor Marton RetType{CharPtrTy}), 201911d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2020db4d5f70SGabor Marton 2021a787a4edSGabor Marton QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy)); 2022db4d5f70SGabor Marton 2023db4d5f70SGabor Marton // int execv(const char *path, char *const argv[]); 202411d2e63aSGabor Marton addToFunctionSummaryMap( 202511d2e63aSGabor Marton "execv", 202611d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}), 2027febe7503SGabor Marton Summary(NoEvalCall) 2028febe7503SGabor Marton .Case({ReturnValueCondition(WithinRange, SingleValue(-1))}) 2029febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 2030db4d5f70SGabor Marton 2031db4d5f70SGabor Marton // int execvp(const char *file, char *const argv[]); 203211d2e63aSGabor Marton addToFunctionSummaryMap( 203311d2e63aSGabor Marton "execvp", 203411d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}), 2035febe7503SGabor Marton Summary(NoEvalCall) 2036febe7503SGabor Marton .Case({ReturnValueCondition(WithinRange, SingleValue(-1))}) 2037febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 2038db4d5f70SGabor Marton 2039db4d5f70SGabor Marton // int getopt(int argc, char * const argv[], const char *optstring); 2040db4d5f70SGabor Marton addToFunctionSummaryMap( 2041db4d5f70SGabor Marton "getopt", 204211d2e63aSGabor Marton Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy}, 204311d2e63aSGabor Marton RetType{IntTy}), 204411d2e63aSGabor Marton Summary(NoEvalCall) 2045febe7503SGabor Marton .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))}) 2046db4d5f70SGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2047db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 2048db4d5f70SGabor Marton .ArgConstraint(NotNull(ArgNo(2)))); 20493ff220deSGabor Marton 2050a787a4edSGabor Marton Optional<QualType> StructSockaddrTy = lookupTy("sockaddr"); 2051a787a4edSGabor Marton Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy); 2052a787a4edSGabor Marton Optional<QualType> ConstStructSockaddrPtrTy = 2053a787a4edSGabor Marton getPointerTy(getConstTy(StructSockaddrTy)); 2054a787a4edSGabor Marton Optional<QualType> StructSockaddrPtrRestrictTy = 2055a787a4edSGabor Marton getRestrictTy(StructSockaddrPtrTy); 2056a787a4edSGabor Marton Optional<QualType> ConstStructSockaddrPtrRestrictTy = 2057a787a4edSGabor Marton getRestrictTy(ConstStructSockaddrPtrTy); 2058a787a4edSGabor Marton Optional<QualType> Socklen_tTy = lookupTy("socklen_t"); 2059a787a4edSGabor Marton Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy); 2060a787a4edSGabor Marton Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy); 2061a787a4edSGabor Marton Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy); 20623ff220deSGabor Marton 20633ff220deSGabor Marton // In 'socket.h' of some libc implementations with C99, sockaddr parameter 20643ff220deSGabor Marton // is a transparent union of the underlying sockaddr_ family of pointers 20653ff220deSGabor Marton // instead of being a pointer to struct sockaddr. In these cases, the 20663ff220deSGabor Marton // standardized signature will not match, thus we try to match with another 20673ff220deSGabor Marton // signature that has the joker Irrelevant type. We also remove those 20683ff220deSGabor Marton // constraints which require pointer types for the sockaddr param. 2069a787a4edSGabor Marton auto Accept = 2070a787a4edSGabor Marton Summary(NoEvalCall) 2071febe7503SGabor Marton .Case(ReturnsFileDescriptor) 2072a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))); 20733ff220deSGabor Marton if (!addToFunctionSummaryMap( 20743ff220deSGabor Marton "accept", 20753ff220deSGabor Marton // int accept(int socket, struct sockaddr *restrict address, 20763ff220deSGabor Marton // socklen_t *restrict address_len); 2077a787a4edSGabor Marton Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2078a787a4edSGabor Marton Socklen_tPtrRestrictTy}, 20793ff220deSGabor Marton RetType{IntTy}), 20803ff220deSGabor Marton Accept)) 20813ff220deSGabor Marton addToFunctionSummaryMap( 20823ff220deSGabor Marton "accept", 2083a787a4edSGabor Marton Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 20843ff220deSGabor Marton RetType{IntTy}), 20853ff220deSGabor Marton Accept); 20863ff220deSGabor Marton 20873ff220deSGabor Marton // int bind(int socket, const struct sockaddr *address, socklen_t 20883ff220deSGabor Marton // address_len); 20893ff220deSGabor Marton if (!addToFunctionSummaryMap( 20903ff220deSGabor Marton "bind", 209111d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, 209211d2e63aSGabor Marton RetType{IntTy}), 209311d2e63aSGabor Marton Summary(NoEvalCall) 2094b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 20953ff220deSGabor Marton .ArgConstraint( 20963ff220deSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax))) 20973ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 20983ff220deSGabor Marton .ArgConstraint( 20993ff220deSGabor Marton BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2))) 2100a787a4edSGabor Marton .ArgConstraint( 2101a787a4edSGabor Marton ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))))) 21023ff220deSGabor Marton // Do not add constraints on sockaddr. 21033ff220deSGabor Marton addToFunctionSummaryMap( 210411d2e63aSGabor Marton "bind", 210511d2e63aSGabor Marton Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), 210611d2e63aSGabor Marton Summary(NoEvalCall) 2107b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 21083ff220deSGabor Marton .ArgConstraint( 21093ff220deSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax))) 211011d2e63aSGabor Marton .ArgConstraint( 211111d2e63aSGabor Marton ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))); 21123ff220deSGabor Marton 21133ff220deSGabor Marton // int getpeername(int socket, struct sockaddr *restrict address, 21143ff220deSGabor Marton // socklen_t *restrict address_len); 21153ff220deSGabor Marton if (!addToFunctionSummaryMap( 211611d2e63aSGabor Marton "getpeername", 211711d2e63aSGabor Marton Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2118a787a4edSGabor Marton Socklen_tPtrRestrictTy}, 211911d2e63aSGabor Marton RetType{IntTy}), 212011d2e63aSGabor Marton Summary(NoEvalCall) 2121b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 212211d2e63aSGabor Marton .ArgConstraint( 212311d2e63aSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax))) 21243ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 21253ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(2))))) 21263ff220deSGabor Marton addToFunctionSummaryMap( 21273ff220deSGabor Marton "getpeername", 212811d2e63aSGabor Marton Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 212911d2e63aSGabor Marton RetType{IntTy}), 213011d2e63aSGabor Marton Summary(NoEvalCall) 2131b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 21323ff220deSGabor Marton .ArgConstraint( 21333ff220deSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 21343ff220deSGabor Marton 21353ff220deSGabor Marton // int getsockname(int socket, struct sockaddr *restrict address, 21363ff220deSGabor Marton // socklen_t *restrict address_len); 21373ff220deSGabor Marton if (!addToFunctionSummaryMap( 213811d2e63aSGabor Marton "getsockname", 213911d2e63aSGabor Marton Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2140a787a4edSGabor Marton Socklen_tPtrRestrictTy}, 214111d2e63aSGabor Marton RetType{IntTy}), 214211d2e63aSGabor Marton Summary(NoEvalCall) 2143b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 214411d2e63aSGabor Marton .ArgConstraint( 214511d2e63aSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax))) 21463ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 21473ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(2))))) 21483ff220deSGabor Marton addToFunctionSummaryMap( 21493ff220deSGabor Marton "getsockname", 215011d2e63aSGabor Marton Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 215111d2e63aSGabor Marton RetType{IntTy}), 215211d2e63aSGabor Marton Summary(NoEvalCall) 2153b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 21543ff220deSGabor Marton .ArgConstraint( 21553ff220deSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 21563ff220deSGabor Marton 21573ff220deSGabor Marton // int connect(int socket, const struct sockaddr *address, socklen_t 21583ff220deSGabor Marton // address_len); 21593ff220deSGabor Marton if (!addToFunctionSummaryMap( 21603ff220deSGabor Marton "connect", 216111d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, 216211d2e63aSGabor Marton RetType{IntTy}), 216311d2e63aSGabor Marton Summary(NoEvalCall) 2164b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 21653ff220deSGabor Marton .ArgConstraint( 21663ff220deSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax))) 21673ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(1))))) 21683ff220deSGabor Marton addToFunctionSummaryMap( 216911d2e63aSGabor Marton "connect", 217011d2e63aSGabor Marton Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), 217111d2e63aSGabor Marton Summary(NoEvalCall) 2172b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 217311d2e63aSGabor Marton .ArgConstraint( 217411d2e63aSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 21753ff220deSGabor Marton 2176a787a4edSGabor Marton auto Recvfrom = 2177a787a4edSGabor Marton Summary(NoEvalCall) 2178b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2179b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 2180a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 21813ff220deSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 21823ff220deSGabor Marton /*BufSize=*/ArgNo(2))); 2183a787a4edSGabor Marton if (!addToFunctionSummaryMap( 21843ff220deSGabor Marton "recvfrom", 21853ff220deSGabor Marton // ssize_t recvfrom(int socket, void *restrict buffer, 21863ff220deSGabor Marton // size_t length, 21873ff220deSGabor Marton // int flags, struct sockaddr *restrict address, 21883ff220deSGabor Marton // socklen_t *restrict address_len); 21893ff220deSGabor Marton Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, 2190a787a4edSGabor Marton StructSockaddrPtrRestrictTy, 2191a787a4edSGabor Marton Socklen_tPtrRestrictTy}, 2192a787a4edSGabor Marton RetType{Ssize_tTy}), 21933ff220deSGabor Marton Recvfrom)) 21943ff220deSGabor Marton addToFunctionSummaryMap( 21953ff220deSGabor Marton "recvfrom", 21963ff220deSGabor Marton Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, 2197a787a4edSGabor Marton Irrelevant, Socklen_tPtrRestrictTy}, 2198a787a4edSGabor Marton RetType{Ssize_tTy}), 21993ff220deSGabor Marton Recvfrom); 22003ff220deSGabor Marton 2201a787a4edSGabor Marton auto Sendto = 2202a787a4edSGabor Marton Summary(NoEvalCall) 2203b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2204b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 2205a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 22063ff220deSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 22073ff220deSGabor Marton /*BufSize=*/ArgNo(2))); 2208a787a4edSGabor Marton if (!addToFunctionSummaryMap( 22093ff220deSGabor Marton "sendto", 22103ff220deSGabor Marton // ssize_t sendto(int socket, const void *message, size_t length, 22113ff220deSGabor Marton // int flags, const struct sockaddr *dest_addr, 22123ff220deSGabor Marton // socklen_t dest_len); 22133ff220deSGabor Marton Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, 2214a787a4edSGabor Marton ConstStructSockaddrPtrTy, Socklen_tTy}, 2215a787a4edSGabor Marton RetType{Ssize_tTy}), 22163ff220deSGabor Marton Sendto)) 22173ff220deSGabor Marton addToFunctionSummaryMap( 22183ff220deSGabor Marton "sendto", 22193ff220deSGabor Marton Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant, 2220a787a4edSGabor Marton Socklen_tTy}, 2221a787a4edSGabor Marton RetType{Ssize_tTy}), 22223ff220deSGabor Marton Sendto); 22233ff220deSGabor Marton 22243ff220deSGabor Marton // int listen(int sockfd, int backlog); 222511d2e63aSGabor Marton addToFunctionSummaryMap("listen", 222611d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), 222711d2e63aSGabor Marton Summary(NoEvalCall) 2228b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 222911d2e63aSGabor Marton .ArgConstraint(ArgumentCondition( 223011d2e63aSGabor Marton 0, WithinRange, Range(0, IntMax)))); 22313ff220deSGabor Marton 22323ff220deSGabor Marton // ssize_t recv(int sockfd, void *buf, size_t len, int flags); 22333ff220deSGabor Marton addToFunctionSummaryMap( 2234a787a4edSGabor Marton "recv", 223511d2e63aSGabor Marton Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy}, 223611d2e63aSGabor Marton RetType{Ssize_tTy}), 223711d2e63aSGabor Marton Summary(NoEvalCall) 2238b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2239b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 2240a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 22413ff220deSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 22423ff220deSGabor Marton /*BufSize=*/ArgNo(2)))); 22433ff220deSGabor Marton 2244a787a4edSGabor Marton Optional<QualType> StructMsghdrTy = lookupTy("msghdr"); 2245a787a4edSGabor Marton Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy); 2246a787a4edSGabor Marton Optional<QualType> ConstStructMsghdrPtrTy = 2247a787a4edSGabor Marton getPointerTy(getConstTy(StructMsghdrTy)); 22483ff220deSGabor Marton 22493ff220deSGabor Marton // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); 2250b40b3196SGabor Marton addToFunctionSummaryMap( 2251b40b3196SGabor Marton "recvmsg", 225211d2e63aSGabor Marton Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy}, 225311d2e63aSGabor Marton RetType{Ssize_tTy}), 225411d2e63aSGabor Marton Summary(NoEvalCall) 2255b40b3196SGabor Marton .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 2256b40b3196SGabor Marton .ArgConstraint( 2257b40b3196SGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 22583ff220deSGabor Marton 22593ff220deSGabor Marton // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); 22603ff220deSGabor Marton addToFunctionSummaryMap( 226111d2e63aSGabor Marton "sendmsg", 226211d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy}, 226311d2e63aSGabor Marton RetType{Ssize_tTy}), 226411d2e63aSGabor Marton Summary(NoEvalCall) 2265b40b3196SGabor Marton .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 226611d2e63aSGabor Marton .ArgConstraint( 226711d2e63aSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 22683ff220deSGabor Marton 22693ff220deSGabor Marton // int setsockopt(int socket, int level, int option_name, 22703ff220deSGabor Marton // const void *option_value, socklen_t option_len); 22713ff220deSGabor Marton addToFunctionSummaryMap( 22723ff220deSGabor Marton "setsockopt", 227311d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy}, 227411d2e63aSGabor Marton RetType{IntTy}), 227511d2e63aSGabor Marton Summary(NoEvalCall) 2276b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 22773ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(3))) 22783ff220deSGabor Marton .ArgConstraint( 22793ff220deSGabor Marton BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4))) 22803ff220deSGabor Marton .ArgConstraint( 2281a787a4edSGabor Marton ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax)))); 22823ff220deSGabor Marton 22833ff220deSGabor Marton // int getsockopt(int socket, int level, int option_name, 22843ff220deSGabor Marton // void *restrict option_value, 22853ff220deSGabor Marton // socklen_t *restrict option_len); 22863ff220deSGabor Marton addToFunctionSummaryMap( 228711d2e63aSGabor Marton "getsockopt", 228811d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy, 2289a787a4edSGabor Marton Socklen_tPtrRestrictTy}, 229011d2e63aSGabor Marton RetType{IntTy}), 229111d2e63aSGabor Marton Summary(NoEvalCall) 2292b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 22933ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(3))) 22943ff220deSGabor Marton .ArgConstraint(NotNull(ArgNo(4)))); 22953ff220deSGabor Marton 22963ff220deSGabor Marton // ssize_t send(int sockfd, const void *buf, size_t len, int flags); 22973ff220deSGabor Marton addToFunctionSummaryMap( 2298a787a4edSGabor Marton "send", 229911d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy}, 230011d2e63aSGabor Marton RetType{Ssize_tTy}), 230111d2e63aSGabor Marton Summary(NoEvalCall) 2302b40b3196SGabor Marton .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2303b40b3196SGabor Marton ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))}) 2304a787a4edSGabor Marton .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 23053ff220deSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 23063ff220deSGabor Marton /*BufSize=*/ArgNo(2)))); 23073ff220deSGabor Marton 23083ff220deSGabor Marton // int socketpair(int domain, int type, int protocol, int sv[2]); 230911d2e63aSGabor Marton addToFunctionSummaryMap( 231011d2e63aSGabor Marton "socketpair", 231111d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}), 2312b40b3196SGabor Marton Summary(NoEvalCall) 2313b40b3196SGabor Marton .Case(ReturnsZeroOrMinusOne) 2314b40b3196SGabor Marton .ArgConstraint(NotNull(ArgNo(3)))); 23153ff220deSGabor Marton 23163ff220deSGabor Marton // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, 23173ff220deSGabor Marton // char *restrict node, socklen_t nodelen, 23183ff220deSGabor Marton // char *restrict service, 23193ff220deSGabor Marton // socklen_t servicelen, int flags); 23203ff220deSGabor Marton // 23213ff220deSGabor Marton // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr 23223ff220deSGabor Marton // parameter is never handled as a transparent union in netdb.h 23233ff220deSGabor Marton addToFunctionSummaryMap( 23243ff220deSGabor Marton "getnameinfo", 232511d2e63aSGabor Marton Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy, 2326a787a4edSGabor Marton CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy, 2327a787a4edSGabor Marton Socklen_tTy, IntTy}, 232811d2e63aSGabor Marton RetType{IntTy}), 232911d2e63aSGabor Marton Summary(NoEvalCall) 23303ff220deSGabor Marton .ArgConstraint( 23313ff220deSGabor Marton BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))) 23323ff220deSGabor Marton .ArgConstraint( 2333a787a4edSGabor Marton ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax))) 23343ff220deSGabor Marton .ArgConstraint( 23353ff220deSGabor Marton BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3))) 23363ff220deSGabor Marton .ArgConstraint( 2337a787a4edSGabor Marton ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax))) 23383ff220deSGabor Marton .ArgConstraint( 23393ff220deSGabor Marton BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5))) 23403ff220deSGabor Marton .ArgConstraint( 2341a787a4edSGabor Marton ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax)))); 2342f0b9dbcfSGabor Marton 2343f0b9dbcfSGabor Marton Optional<QualType> StructUtimbufTy = lookupTy("utimbuf"); 2344f0b9dbcfSGabor Marton Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy); 2345f0b9dbcfSGabor Marton 2346f0b9dbcfSGabor Marton // int utime(const char *filename, struct utimbuf *buf); 2347f0b9dbcfSGabor Marton addToFunctionSummaryMap( 234811d2e63aSGabor Marton "utime", 234911d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}), 2350febe7503SGabor Marton Summary(NoEvalCall) 2351febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2352febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 2353f0b9dbcfSGabor Marton 2354f0b9dbcfSGabor Marton Optional<QualType> StructTimespecTy = lookupTy("timespec"); 2355f0b9dbcfSGabor Marton Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy); 2356f0b9dbcfSGabor Marton Optional<QualType> ConstStructTimespecPtrTy = 2357f0b9dbcfSGabor Marton getPointerTy(getConstTy(StructTimespecTy)); 2358f0b9dbcfSGabor Marton 2359f0b9dbcfSGabor Marton // int futimens(int fd, const struct timespec times[2]); 2360f0b9dbcfSGabor Marton addToFunctionSummaryMap( 236111d2e63aSGabor Marton "futimens", 236211d2e63aSGabor Marton Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}), 236311d2e63aSGabor Marton Summary(NoEvalCall) 2364febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 236511d2e63aSGabor Marton .ArgConstraint( 236611d2e63aSGabor Marton ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2367f0b9dbcfSGabor Marton 2368f0b9dbcfSGabor Marton // int utimensat(int dirfd, const char *pathname, 2369f0b9dbcfSGabor Marton // const struct timespec times[2], int flags); 2370febe7503SGabor Marton addToFunctionSummaryMap("utimensat", 2371febe7503SGabor Marton Signature(ArgTypes{IntTy, ConstCharPtrTy, 2372febe7503SGabor Marton ConstStructTimespecPtrTy, IntTy}, 237311d2e63aSGabor Marton RetType{IntTy}), 2374febe7503SGabor Marton Summary(NoEvalCall) 2375febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2376febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2377f0b9dbcfSGabor Marton 2378f0b9dbcfSGabor Marton Optional<QualType> StructTimevalTy = lookupTy("timeval"); 2379f0b9dbcfSGabor Marton Optional<QualType> ConstStructTimevalPtrTy = 2380f0b9dbcfSGabor Marton getPointerTy(getConstTy(StructTimevalTy)); 2381f0b9dbcfSGabor Marton 2382f0b9dbcfSGabor Marton // int utimes(const char *filename, const struct timeval times[2]); 2383f0b9dbcfSGabor Marton addToFunctionSummaryMap( 238411d2e63aSGabor Marton "utimes", 238511d2e63aSGabor Marton Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy}, 238611d2e63aSGabor Marton RetType{IntTy}), 2387febe7503SGabor Marton Summary(NoEvalCall) 2388febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2389febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 2390f0b9dbcfSGabor Marton 2391f0b9dbcfSGabor Marton // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); 2392f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2393f0b9dbcfSGabor Marton "nanosleep", 239411d2e63aSGabor Marton Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy}, 239511d2e63aSGabor Marton RetType{IntTy}), 2396febe7503SGabor Marton Summary(NoEvalCall) 2397febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2398febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(0)))); 2399f0b9dbcfSGabor Marton 2400f0b9dbcfSGabor Marton Optional<QualType> Time_tTy = lookupTy("time_t"); 2401f0b9dbcfSGabor Marton Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy)); 2402f0b9dbcfSGabor Marton Optional<QualType> ConstTime_tPtrRestrictTy = 2403f0b9dbcfSGabor Marton getRestrictTy(ConstTime_tPtrTy); 2404f0b9dbcfSGabor Marton 2405f0b9dbcfSGabor Marton Optional<QualType> StructTmTy = lookupTy("tm"); 2406f0b9dbcfSGabor Marton Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy); 2407f0b9dbcfSGabor Marton Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy); 2408f0b9dbcfSGabor Marton Optional<QualType> ConstStructTmPtrTy = 2409f0b9dbcfSGabor Marton getPointerTy(getConstTy(StructTmTy)); 2410f0b9dbcfSGabor Marton Optional<QualType> ConstStructTmPtrRestrictTy = 2411f0b9dbcfSGabor Marton getRestrictTy(ConstStructTmPtrTy); 2412f0b9dbcfSGabor Marton 2413f0b9dbcfSGabor Marton // struct tm * localtime(const time_t *tp); 2414f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2415f0b9dbcfSGabor Marton "localtime", 241611d2e63aSGabor Marton Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}), 241711d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2418f0b9dbcfSGabor Marton 2419f0b9dbcfSGabor Marton // struct tm *localtime_r(const time_t *restrict timer, 2420f0b9dbcfSGabor Marton // struct tm *restrict result); 2421f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2422f0b9dbcfSGabor Marton "localtime_r", 242311d2e63aSGabor Marton Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy}, 242411d2e63aSGabor Marton RetType{StructTmPtrTy}), 242511d2e63aSGabor Marton Summary(NoEvalCall) 2426f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2427f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2428f0b9dbcfSGabor Marton 2429f0b9dbcfSGabor Marton // char *asctime_r(const struct tm *restrict tm, char *restrict buf); 2430f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2431f0b9dbcfSGabor Marton "asctime_r", 243211d2e63aSGabor Marton Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy}, 243311d2e63aSGabor Marton RetType{CharPtrTy}), 243411d2e63aSGabor Marton Summary(NoEvalCall) 2435f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2436f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 2437f0b9dbcfSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2438f0b9dbcfSGabor Marton /*MinBufSize=*/BVF.getValue(26, IntTy)))); 2439f0b9dbcfSGabor Marton 2440f0b9dbcfSGabor Marton // char *ctime_r(const time_t *timep, char *buf); 244111d2e63aSGabor Marton addToFunctionSummaryMap( 244211d2e63aSGabor Marton "ctime_r", 244311d2e63aSGabor Marton Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}), 244411d2e63aSGabor Marton Summary(NoEvalCall) 2445f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2446f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(1))) 2447f0b9dbcfSGabor Marton .ArgConstraint(BufferSize( 2448f0b9dbcfSGabor Marton /*Buffer=*/ArgNo(1), 2449f0b9dbcfSGabor Marton /*MinBufSize=*/BVF.getValue(26, IntTy)))); 2450f0b9dbcfSGabor Marton 2451f0b9dbcfSGabor Marton // struct tm *gmtime_r(const time_t *restrict timer, 2452f0b9dbcfSGabor Marton // struct tm *restrict result); 2453f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2454f0b9dbcfSGabor Marton "gmtime_r", 245511d2e63aSGabor Marton Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy}, 245611d2e63aSGabor Marton RetType{StructTmPtrTy}), 245711d2e63aSGabor Marton Summary(NoEvalCall) 2458f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2459f0b9dbcfSGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2460f0b9dbcfSGabor Marton 2461f0b9dbcfSGabor Marton // struct tm * gmtime(const time_t *tp); 2462f0b9dbcfSGabor Marton addToFunctionSummaryMap( 246311d2e63aSGabor Marton "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}), 246411d2e63aSGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2465f0b9dbcfSGabor Marton 2466f0b9dbcfSGabor Marton Optional<QualType> Clockid_tTy = lookupTy("clockid_t"); 2467f0b9dbcfSGabor Marton 2468f0b9dbcfSGabor Marton // int clock_gettime(clockid_t clock_id, struct timespec *tp); 246911d2e63aSGabor Marton addToFunctionSummaryMap( 247011d2e63aSGabor Marton "clock_gettime", 247111d2e63aSGabor Marton Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}), 2472febe7503SGabor Marton Summary(NoEvalCall) 2473febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2474febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2475f0b9dbcfSGabor Marton 2476f0b9dbcfSGabor Marton Optional<QualType> StructItimervalTy = lookupTy("itimerval"); 2477f0b9dbcfSGabor Marton Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy); 2478f0b9dbcfSGabor Marton 2479f0b9dbcfSGabor Marton // int getitimer(int which, struct itimerval *curr_value); 248011d2e63aSGabor Marton addToFunctionSummaryMap( 248111d2e63aSGabor Marton "getitimer", 248211d2e63aSGabor Marton Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}), 2483febe7503SGabor Marton Summary(NoEvalCall) 2484febe7503SGabor Marton .Case(ReturnsZeroOrMinusOne) 2485febe7503SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2486d0128058SGabor Marton 2487d0128058SGabor Marton Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t"); 2488d0128058SGabor Marton Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy); 2489d0128058SGabor Marton Optional<QualType> Pthread_tTy = lookupTy("pthread_t"); 2490d0128058SGabor Marton Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy); 2491d0128058SGabor Marton Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy); 2492d0128058SGabor Marton Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t"); 2493d0128058SGabor Marton Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy); 2494d0128058SGabor Marton Optional<QualType> Pthread_mutex_tPtrRestrictTy = 2495d0128058SGabor Marton getRestrictTy(Pthread_mutex_tPtrTy); 2496d0128058SGabor Marton Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t"); 2497d0128058SGabor Marton Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy); 2498d0128058SGabor Marton Optional<QualType> ConstPthread_attr_tPtrTy = 2499d0128058SGabor Marton getPointerTy(getConstTy(Pthread_attr_tTy)); 2500d0128058SGabor Marton Optional<QualType> ConstPthread_attr_tPtrRestrictTy = 2501d0128058SGabor Marton getRestrictTy(ConstPthread_attr_tPtrTy); 2502d0128058SGabor Marton Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t"); 2503d0128058SGabor Marton Optional<QualType> ConstPthread_mutexattr_tPtrTy = 2504d0128058SGabor Marton getPointerTy(getConstTy(Pthread_mutexattr_tTy)); 2505d0128058SGabor Marton Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy = 2506d0128058SGabor Marton getRestrictTy(ConstPthread_mutexattr_tPtrTy); 2507d0128058SGabor Marton 2508d0128058SGabor Marton QualType PthreadStartRoutineTy = getPointerTy( 2509d0128058SGabor Marton ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy, 2510d0128058SGabor Marton FunctionProtoType::ExtProtoInfo())); 2511d0128058SGabor Marton 2512d0128058SGabor Marton // int pthread_cond_signal(pthread_cond_t *cond); 2513d0128058SGabor Marton // int pthread_cond_broadcast(pthread_cond_t *cond); 2514d0128058SGabor Marton addToFunctionSummaryMap( 2515d0128058SGabor Marton {"pthread_cond_signal", "pthread_cond_broadcast"}, 2516d0128058SGabor Marton Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}), 2517d0128058SGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2518d0128058SGabor Marton 2519d0128058SGabor Marton // int pthread_create(pthread_t *restrict thread, 2520d0128058SGabor Marton // const pthread_attr_t *restrict attr, 2521d0128058SGabor Marton // void *(*start_routine)(void*), void *restrict arg); 2522d0128058SGabor Marton addToFunctionSummaryMap( 2523d0128058SGabor Marton "pthread_create", 2524d0128058SGabor Marton Signature(ArgTypes{Pthread_tPtrRestrictTy, 2525d0128058SGabor Marton ConstPthread_attr_tPtrRestrictTy, 2526d0128058SGabor Marton PthreadStartRoutineTy, VoidPtrRestrictTy}, 2527d0128058SGabor Marton RetType{IntTy}), 2528d0128058SGabor Marton Summary(NoEvalCall) 2529d0128058SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2530d0128058SGabor Marton .ArgConstraint(NotNull(ArgNo(2)))); 2531d0128058SGabor Marton 2532d0128058SGabor Marton // int pthread_attr_destroy(pthread_attr_t *attr); 2533d0128058SGabor Marton // int pthread_attr_init(pthread_attr_t *attr); 2534d0128058SGabor Marton addToFunctionSummaryMap( 2535d0128058SGabor Marton {"pthread_attr_destroy", "pthread_attr_init"}, 2536d0128058SGabor Marton Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}), 2537d0128058SGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2538d0128058SGabor Marton 2539d0128058SGabor Marton // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, 2540d0128058SGabor Marton // size_t *restrict stacksize); 2541d0128058SGabor Marton // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, 2542d0128058SGabor Marton // size_t *restrict guardsize); 2543d0128058SGabor Marton addToFunctionSummaryMap( 2544d0128058SGabor Marton {"pthread_attr_getstacksize", "pthread_attr_getguardsize"}, 2545d0128058SGabor Marton Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy}, 2546d0128058SGabor Marton RetType{IntTy}), 2547d0128058SGabor Marton Summary(NoEvalCall) 2548d0128058SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2549d0128058SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2550d0128058SGabor Marton 2551d0128058SGabor Marton // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); 2552d0128058SGabor Marton // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); 2553d0128058SGabor Marton addToFunctionSummaryMap( 2554d0128058SGabor Marton {"pthread_attr_setstacksize", "pthread_attr_setguardsize"}, 2555d0128058SGabor Marton Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}), 2556d0128058SGabor Marton Summary(NoEvalCall) 2557d0128058SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 2558d0128058SGabor Marton .ArgConstraint( 2559d0128058SGabor Marton ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); 2560d0128058SGabor Marton 2561d0128058SGabor Marton // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const 2562d0128058SGabor Marton // pthread_mutexattr_t *restrict attr); 2563d0128058SGabor Marton addToFunctionSummaryMap( 2564d0128058SGabor Marton "pthread_mutex_init", 2565d0128058SGabor Marton Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy, 2566d0128058SGabor Marton ConstPthread_mutexattr_tPtrRestrictTy}, 2567d0128058SGabor Marton RetType{IntTy}), 2568d0128058SGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2569d0128058SGabor Marton 2570d0128058SGabor Marton // int pthread_mutex_destroy(pthread_mutex_t *mutex); 2571d0128058SGabor Marton // int pthread_mutex_lock(pthread_mutex_t *mutex); 2572d0128058SGabor Marton // int pthread_mutex_trylock(pthread_mutex_t *mutex); 2573d0128058SGabor Marton // int pthread_mutex_unlock(pthread_mutex_t *mutex); 2574d0128058SGabor Marton addToFunctionSummaryMap( 2575d0128058SGabor Marton {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock", 2576d0128058SGabor Marton "pthread_mutex_unlock"}, 2577d0128058SGabor Marton Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}), 2578d0128058SGabor Marton Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2579db4d5f70SGabor Marton } 2580db4d5f70SGabor Marton 25811525232eSGabor Marton // Functions for testing. 25821525232eSGabor Marton if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) { 258362e747f6SGabor Marton addToFunctionSummaryMap( 2584a7cb951fSGabor Marton "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}), 2585a7cb951fSGabor Marton Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0)))); 2586a7cb951fSGabor Marton 2587a7cb951fSGabor Marton // Test range values. 2588a7cb951fSGabor Marton addToFunctionSummaryMap( 2589a7cb951fSGabor Marton "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2590a7cb951fSGabor Marton Summary(EvalCallAsPure) 2591a7cb951fSGabor Marton .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))); 2592a7cb951fSGabor Marton addToFunctionSummaryMap( 2593a7cb951fSGabor Marton "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2594a7cb951fSGabor Marton Summary(EvalCallAsPure) 2595a7cb951fSGabor Marton .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2)))); 2596a7cb951fSGabor Marton addToFunctionSummaryMap("__range_1_2__4_5", 2597a7cb951fSGabor Marton Signature(ArgTypes{IntTy}, RetType{IntTy}), 2598a7cb951fSGabor Marton Summary(EvalCallAsPure) 2599a7cb951fSGabor Marton .ArgConstraint(ArgumentCondition( 2600a7cb951fSGabor Marton 0U, WithinRange, Range({1, 2}, {4, 5})))); 2601a7cb951fSGabor Marton 2602a7cb951fSGabor Marton // Test range kind. 2603a7cb951fSGabor Marton addToFunctionSummaryMap( 2604a7cb951fSGabor Marton "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2605a7cb951fSGabor Marton Summary(EvalCallAsPure) 2606a7cb951fSGabor Marton .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))); 2607a7cb951fSGabor Marton addToFunctionSummaryMap( 2608a7cb951fSGabor Marton "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2609a7cb951fSGabor Marton Summary(EvalCallAsPure) 2610a7cb951fSGabor Marton .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))); 2611a7cb951fSGabor Marton 2612a7cb951fSGabor Marton addToFunctionSummaryMap( 261362e747f6SGabor Marton "__two_constrained_args", 261411d2e63aSGabor Marton Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), 261511d2e63aSGabor Marton Summary(EvalCallAsPure) 261662e747f6SGabor Marton .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))) 261762e747f6SGabor Marton .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1)))); 261862e747f6SGabor Marton addToFunctionSummaryMap( 261911d2e63aSGabor Marton "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}), 262011d2e63aSGabor Marton Summary(EvalCallAsPure) 262162e747f6SGabor Marton .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))) 262262e747f6SGabor Marton .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2)))); 262362e747f6SGabor Marton addToFunctionSummaryMap( 262462e747f6SGabor Marton "__defaultparam", 262511d2e63aSGabor Marton Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}), 262611d2e63aSGabor Marton Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0)))); 262711d2e63aSGabor Marton addToFunctionSummaryMap( 262811d2e63aSGabor Marton "__variadic", 262911d2e63aSGabor Marton Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}), 263011d2e63aSGabor Marton Summary(EvalCallAsPure) 26318f961399SGabor Marton .ArgConstraint(NotNull(ArgNo(0))) 263262e747f6SGabor Marton .ArgConstraint(NotNull(ArgNo(1)))); 2633bd03ef19SGabor Marton addToFunctionSummaryMap( 2634bd03ef19SGabor Marton "__buf_size_arg_constraint", 263511d2e63aSGabor Marton Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}), 263611d2e63aSGabor Marton Summary(EvalCallAsPure) 2637bd03ef19SGabor Marton .ArgConstraint( 2638bd03ef19SGabor Marton BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))); 263941928c97SGabor Marton addToFunctionSummaryMap( 264041928c97SGabor Marton "__buf_size_arg_constraint_mul", 264111d2e63aSGabor Marton Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}), 264211d2e63aSGabor Marton Summary(EvalCallAsPure) 264341928c97SGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), 264441928c97SGabor Marton /*BufSizeMultiplier=*/ArgNo(2)))); 2645fe0972d3SGabor Marton addToFunctionSummaryMap( 2646f0b9dbcfSGabor Marton "__buf_size_arg_constraint_concrete", 264711d2e63aSGabor Marton Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}), 264811d2e63aSGabor Marton Summary(EvalCallAsPure) 2649f0b9dbcfSGabor Marton .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), 2650f0b9dbcfSGabor Marton /*BufSize=*/BVF.getValue(10, IntTy)))); 2651f0b9dbcfSGabor Marton addToFunctionSummaryMap( 2652fe0972d3SGabor Marton {"__test_restrict_param_0", "__test_restrict_param_1", 2653fe0972d3SGabor Marton "__test_restrict_param_2"}, 2654fe0972d3SGabor Marton Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}), 2655fe0972d3SGabor Marton Summary(EvalCallAsPure)); 26561525232eSGabor Marton } 2657c7635040SValeriy Savchenko 2658c7635040SValeriy Savchenko SummariesInitialized = true; 2659bba497fbSArtem Dergachev } 2660bba497fbSArtem Dergachev 2661bba497fbSArtem Dergachev void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) { 2662ff4492c8SGabor Marton auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>(); 2663*edde4efcSBalazs Benics const AnalyzerOptions &Opts = mgr.getAnalyzerOptions(); 2664ff4492c8SGabor Marton Checker->DisplayLoadedSummaries = 2665*edde4efcSBalazs Benics Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries"); 2666*edde4efcSBalazs Benics Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX"); 2667*edde4efcSBalazs Benics Checker->ShouldAssumeControlledEnvironment = 2668*edde4efcSBalazs Benics Opts.ShouldAssumeControlledEnvironment; 2669bba497fbSArtem Dergachev } 2670058a7a45SKristof Umann 267125bbe234SZurab Tsinadze bool ento::shouldRegisterStdCLibraryFunctionsChecker( 267225bbe234SZurab Tsinadze const CheckerManager &mgr) { 2673058a7a45SKristof Umann return true; 2674058a7a45SKristof Umann } 267594061df6SGabor Marton 267694061df6SGabor Marton #define REGISTER_CHECKER(name) \ 267794061df6SGabor Marton void ento::register##name(CheckerManager &mgr) { \ 267894061df6SGabor Marton StdLibraryFunctionsChecker *checker = \ 267994061df6SGabor Marton mgr.getChecker<StdLibraryFunctionsChecker>(); \ 268094061df6SGabor Marton checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true; \ 268194061df6SGabor Marton checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] = \ 268294061df6SGabor Marton mgr.getCurrentCheckerName(); \ 268394061df6SGabor Marton } \ 268494061df6SGabor Marton \ 2685bda3dd0dSKirstóf Umann bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } 268694061df6SGabor Marton 268794061df6SGabor Marton REGISTER_CHECKER(StdCLibraryFunctionArgsChecker) 26881525232eSGabor Marton REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker) 2689