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