1 //=== StdLibraryFunctionsChecker.cpp - Model standard functions -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This checker improves modeling of a few simple library functions. 10 // 11 // This checker provides a specification format - `Summary' - and 12 // contains descriptions of some library functions in this format. Each 13 // specification contains a list of branches for splitting the program state 14 // upon call, and range constraints on argument and return-value symbols that 15 // are satisfied on each branch. This spec can be expanded to include more 16 // items, like external effects of the function. 17 // 18 // The main difference between this approach and the body farms technique is 19 // in more explicit control over how many branches are produced. For example, 20 // consider standard C function `ispunct(int x)', which returns a non-zero value 21 // iff `x' is a punctuation character, that is, when `x' is in range 22 // ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~']. 23 // `Summary' provides only two branches for this function. However, 24 // any attempt to describe this range with if-statements in the body farm 25 // would result in many more branches. Because each branch needs to be analyzed 26 // independently, this significantly reduces performance. Additionally, 27 // once we consider a branch on which `x' is in range, say, ['!', '/'], 28 // we assume that such branch is an important separate path through the program, 29 // which may lead to false positives because considering this particular path 30 // was not consciously intended, and therefore it might have been unreachable. 31 // 32 // This checker uses eval::Call for modeling pure functions (functions without 33 // side effets), for which their `Summary' is a precise model. This avoids 34 // unnecessary invalidation passes. Conflicts with other checkers are unlikely 35 // because if the function has no other effects, other checkers would probably 36 // never want to improve upon the modeling done by this checker. 37 // 38 // Non-pure functions, for which only partial improvement over the default 39 // behavior is expected, are modeled via check::PostCall, non-intrusively. 40 // 41 // The following standard C functions are currently supported: 42 // 43 // fgetc getline isdigit isupper 44 // fread isalnum isgraph isxdigit 45 // fwrite isalpha islower read 46 // getc isascii isprint write 47 // getchar isblank ispunct 48 // getdelim iscntrl isspace 49 // 50 //===----------------------------------------------------------------------===// 51 52 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 53 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" 54 #include "clang/StaticAnalyzer/Core/Checker.h" 55 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 56 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 57 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 58 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h" 59 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicSize.h" 60 61 using namespace clang; 62 using namespace clang::ento; 63 64 namespace { 65 class StdLibraryFunctionsChecker 66 : public Checker<check::PreCall, check::PostCall, eval::Call> { 67 68 class Summary; 69 70 /// Specify how much the analyzer engine should entrust modeling this function 71 /// to us. If he doesn't, he performs additional invalidations. 72 enum InvalidationKind { NoEvalCall, EvalCallAsPure }; 73 74 // The universal integral type to use in value range descriptions. 75 // Unsigned to make sure overflows are well-defined. 76 typedef uint64_t RangeInt; 77 78 /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is 79 /// a non-negative integer, which less than 5 and not equal to 2. For 80 /// `ComparesToArgument', holds information about how exactly to compare to 81 /// the argument. 82 typedef std::vector<std::pair<RangeInt, RangeInt>> IntRangeVector; 83 84 /// A reference to an argument or return value by its number. 85 /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but 86 /// obviously uint32_t should be enough for all practical purposes. 87 typedef uint32_t ArgNo; 88 static const ArgNo Ret; 89 90 class ValueConstraint; 91 92 // Pointer to the ValueConstraint. We need a copyable, polymorphic and 93 // default initialize able type (vector needs that). A raw pointer was good, 94 // however, we cannot default initialize that. unique_ptr makes the Summary 95 // class non-copyable, therefore not an option. Releasing the copyability 96 // requirement would render the initialization of the Summary map infeasible. 97 using ValueConstraintPtr = std::shared_ptr<ValueConstraint>; 98 99 /// Polymorphic base class that represents a constraint on a given argument 100 /// (or return value) of a function. Derived classes implement different kind 101 /// of constraints, e.g range constraints or correlation between two 102 /// arguments. 103 class ValueConstraint { 104 public: 105 ValueConstraint(ArgNo ArgN) : ArgN(ArgN) {} 106 virtual ~ValueConstraint() {} 107 /// Apply the effects of the constraint on the given program state. If null 108 /// is returned then the constraint is not feasible. 109 virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 110 const Summary &Summary, 111 CheckerContext &C) const = 0; 112 virtual ValueConstraintPtr negate() const { 113 llvm_unreachable("Not implemented"); 114 }; 115 116 // Check whether the constraint is malformed or not. It is malformed if the 117 // specified argument has a mismatch with the given FunctionDecl (e.g. the 118 // arg number is out-of-range of the function's argument list). 119 bool checkValidity(const FunctionDecl *FD) const { 120 const bool ValidArg = ArgN == Ret || ArgN < FD->getNumParams(); 121 assert(ValidArg && "Arg out of range!"); 122 if (!ValidArg) 123 return false; 124 // Subclasses may further refine the validation. 125 return checkSpecificValidity(FD); 126 } 127 ArgNo getArgNo() const { return ArgN; } 128 129 protected: 130 ArgNo ArgN; // Argument to which we apply the constraint. 131 132 /// Do polymorphic sanity check on the constraint. 133 virtual bool checkSpecificValidity(const FunctionDecl *FD) const { 134 return true; 135 } 136 }; 137 138 /// Given a range, should the argument stay inside or outside this range? 139 enum RangeKind { OutOfRange, WithinRange }; 140 141 /// Encapsulates a single range on a single symbol within a branch. 142 class RangeConstraint : public ValueConstraint { 143 RangeKind Kind; // Kind of range definition. 144 IntRangeVector Args; // Polymorphic arguments. 145 146 public: 147 RangeConstraint(ArgNo ArgN, RangeKind Kind, const IntRangeVector &Args) 148 : ValueConstraint(ArgN), Kind(Kind), Args(Args) {} 149 150 const IntRangeVector &getRanges() const { 151 return Args; 152 } 153 154 private: 155 ProgramStateRef applyAsOutOfRange(ProgramStateRef State, 156 const CallEvent &Call, 157 const Summary &Summary) const; 158 ProgramStateRef applyAsWithinRange(ProgramStateRef State, 159 const CallEvent &Call, 160 const Summary &Summary) const; 161 public: 162 ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 163 const Summary &Summary, 164 CheckerContext &C) const override { 165 switch (Kind) { 166 case OutOfRange: 167 return applyAsOutOfRange(State, Call, Summary); 168 case WithinRange: 169 return applyAsWithinRange(State, Call, Summary); 170 } 171 llvm_unreachable("Unknown range kind!"); 172 } 173 174 ValueConstraintPtr negate() const override { 175 RangeConstraint Tmp(*this); 176 switch (Kind) { 177 case OutOfRange: 178 Tmp.Kind = WithinRange; 179 break; 180 case WithinRange: 181 Tmp.Kind = OutOfRange; 182 break; 183 } 184 return std::make_shared<RangeConstraint>(Tmp); 185 } 186 187 bool checkSpecificValidity(const FunctionDecl *FD) const override { 188 const bool ValidArg = 189 getArgType(FD, ArgN)->isIntegralType(FD->getASTContext()); 190 assert(ValidArg && 191 "This constraint should be applied on an integral type"); 192 return ValidArg; 193 } 194 }; 195 196 class ComparisonConstraint : public ValueConstraint { 197 BinaryOperator::Opcode Opcode; 198 ArgNo OtherArgN; 199 200 public: 201 ComparisonConstraint(ArgNo ArgN, BinaryOperator::Opcode Opcode, 202 ArgNo OtherArgN) 203 : ValueConstraint(ArgN), Opcode(Opcode), OtherArgN(OtherArgN) {} 204 ArgNo getOtherArgNo() const { return OtherArgN; } 205 BinaryOperator::Opcode getOpcode() const { return Opcode; } 206 ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 207 const Summary &Summary, 208 CheckerContext &C) const override; 209 }; 210 211 class NotNullConstraint : public ValueConstraint { 212 using ValueConstraint::ValueConstraint; 213 // This variable has a role when we negate the constraint. 214 bool CannotBeNull = true; 215 216 public: 217 ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 218 const Summary &Summary, 219 CheckerContext &C) const override { 220 SVal V = getArgSVal(Call, getArgNo()); 221 if (V.isUndef()) 222 return State; 223 224 DefinedOrUnknownSVal L = V.castAs<DefinedOrUnknownSVal>(); 225 if (!L.getAs<Loc>()) 226 return State; 227 228 return State->assume(L, CannotBeNull); 229 } 230 231 ValueConstraintPtr negate() const override { 232 NotNullConstraint Tmp(*this); 233 Tmp.CannotBeNull = !this->CannotBeNull; 234 return std::make_shared<NotNullConstraint>(Tmp); 235 } 236 237 bool checkSpecificValidity(const FunctionDecl *FD) const override { 238 const bool ValidArg = getArgType(FD, ArgN)->isPointerType(); 239 assert(ValidArg && 240 "This constraint should be applied only on a pointer type"); 241 return ValidArg; 242 } 243 }; 244 245 // Represents a buffer argument with an additional size argument. 246 // E.g. the first two arguments here: 247 // ctime_s(char *buffer, rsize_t bufsz, const time_t *time); 248 // Another example: 249 // size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 250 // // Here, ptr is the buffer, and its minimum size is `size * nmemb`. 251 class BufferSizeConstraint : public ValueConstraint { 252 // The argument which holds the size of the buffer. 253 ArgNo SizeArgN; 254 // The argument which is a multiplier to size. This is set in case of 255 // `fread` like functions where the size is computed as a multiplication of 256 // two arguments. 257 llvm::Optional<ArgNo> SizeMultiplierArgN; 258 // The operator we use in apply. This is negated in negate(). 259 BinaryOperator::Opcode Op = BO_LE; 260 261 public: 262 BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize) 263 : ValueConstraint(Buffer), SizeArgN(BufSize) {} 264 265 BufferSizeConstraint(ArgNo Buffer, ArgNo BufSize, ArgNo BufSizeMultiplier) 266 : ValueConstraint(Buffer), SizeArgN(BufSize), 267 SizeMultiplierArgN(BufSizeMultiplier) {} 268 269 ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 270 const Summary &Summary, 271 CheckerContext &C) const override { 272 SValBuilder &SvalBuilder = C.getSValBuilder(); 273 // The buffer argument. 274 SVal BufV = getArgSVal(Call, getArgNo()); 275 // The size argument. 276 SVal SizeV = getArgSVal(Call, SizeArgN); 277 // Multiply with another argument if given. 278 if (SizeMultiplierArgN) { 279 SVal SizeMulV = getArgSVal(Call, *SizeMultiplierArgN); 280 SizeV = SvalBuilder.evalBinOp(State, BO_Mul, SizeV, SizeMulV, 281 Summary.getArgType(SizeArgN)); 282 } 283 // The dynamic size of the buffer argument, got from the analyzer engine. 284 SVal BufDynSize = getDynamicSizeWithOffset(State, BufV); 285 286 SVal Feasible = SvalBuilder.evalBinOp(State, Op, SizeV, BufDynSize, 287 SvalBuilder.getContext().BoolTy); 288 if (auto F = Feasible.getAs<DefinedOrUnknownSVal>()) 289 return State->assume(*F, true); 290 291 // We can get here only if the size argument or the dynamic size is 292 // undefined. But the dynamic size should never be undefined, only 293 // unknown. So, here, the size of the argument is undefined, i.e. we 294 // cannot apply the constraint. Actually, other checkers like 295 // CallAndMessage should catch this situation earlier, because we call a 296 // function with an uninitialized argument. 297 llvm_unreachable("Size argument or the dynamic size is Undefined"); 298 } 299 300 ValueConstraintPtr negate() const override { 301 BufferSizeConstraint Tmp(*this); 302 Tmp.Op = BinaryOperator::negateComparisonOp(Op); 303 return std::make_shared<BufferSizeConstraint>(Tmp); 304 } 305 }; 306 307 /// The complete list of constraints that defines a single branch. 308 typedef std::vector<ValueConstraintPtr> ConstraintSet; 309 310 using ArgTypes = std::vector<QualType>; 311 312 // A placeholder type, we use it whenever we do not care about the concrete 313 // type in a Signature. 314 const QualType Irrelevant{}; 315 bool static isIrrelevant(QualType T) { return T.isNull(); } 316 317 // The signature of a function we want to describe with a summary. This is a 318 // concessive signature, meaning there may be irrelevant types in the 319 // signature which we do not check against a function with concrete types. 320 struct Signature { 321 const ArgTypes ArgTys; 322 const QualType RetTy; 323 Signature(ArgTypes ArgTys, QualType RetTy) : ArgTys(ArgTys), RetTy(RetTy) { 324 assertRetTypeSuitableForSignature(RetTy); 325 for (size_t I = 0, E = ArgTys.size(); I != E; ++I) { 326 QualType ArgTy = ArgTys[I]; 327 assertArgTypeSuitableForSignature(ArgTy); 328 } 329 } 330 bool matches(const FunctionDecl *FD) const; 331 332 private: 333 static void assertArgTypeSuitableForSignature(QualType T) { 334 assert((T.isNull() || !T->isVoidType()) && 335 "We should have no void types in the spec"); 336 assert((T.isNull() || T.isCanonical()) && 337 "We should only have canonical types in the spec"); 338 } 339 static void assertRetTypeSuitableForSignature(QualType T) { 340 assert((T.isNull() || T.isCanonical()) && 341 "We should only have canonical types in the spec"); 342 } 343 }; 344 345 static QualType getArgType(const FunctionDecl *FD, ArgNo ArgN) { 346 assert(FD && "Function must be set"); 347 QualType T = (ArgN == Ret) 348 ? FD->getReturnType().getCanonicalType() 349 : FD->getParamDecl(ArgN)->getType().getCanonicalType(); 350 return T; 351 } 352 353 using Cases = std::vector<ConstraintSet>; 354 355 /// A summary includes information about 356 /// * function prototype (signature) 357 /// * approach to invalidation, 358 /// * a list of branches - a list of list of ranges - 359 /// A branch represents a path in the exploded graph of a function (which 360 /// is a tree). So, a branch is a series of assumptions. In other words, 361 /// branches represent split states and additional assumptions on top of 362 /// the splitting assumption. 363 /// For example, consider the branches in `isalpha(x)` 364 /// Branch 1) 365 /// x is in range ['A', 'Z'] or in ['a', 'z'] 366 /// then the return value is not 0. (I.e. out-of-range [0, 0]) 367 /// Branch 2) 368 /// x is out-of-range ['A', 'Z'] and out-of-range ['a', 'z'] 369 /// then the return value is 0. 370 /// * a list of argument constraints, that must be true on every branch. 371 /// If these constraints are not satisfied that means a fatal error 372 /// usually resulting in undefined behaviour. 373 /// 374 /// Application of a summary: 375 /// The signature and argument constraints together contain information 376 /// about which functions are handled by the summary. The signature can use 377 /// "wildcards", i.e. Irrelevant types. Irrelevant type of a parameter in 378 /// a signature means that type is not compared to the type of the parameter 379 /// in the found FunctionDecl. Argument constraints may specify additional 380 /// rules for the given parameter's type, those rules are checked once the 381 /// signature is matched. 382 class Summary { 383 const Signature Sign; 384 const InvalidationKind InvalidationKd; 385 Cases CaseConstraints; 386 ConstraintSet ArgConstraints; 387 388 // The function to which the summary applies. This is set after lookup and 389 // match to the signature. 390 const FunctionDecl *FD = nullptr; 391 392 public: 393 Summary(ArgTypes ArgTys, QualType RetTy, InvalidationKind InvalidationKd) 394 : Sign(ArgTys, RetTy), InvalidationKd(InvalidationKd) {} 395 396 Summary &Case(ConstraintSet&& CS) { 397 CaseConstraints.push_back(std::move(CS)); 398 return *this; 399 } 400 Summary &ArgConstraint(ValueConstraintPtr VC) { 401 ArgConstraints.push_back(VC); 402 return *this; 403 } 404 405 InvalidationKind getInvalidationKd() const { return InvalidationKd; } 406 const Cases &getCaseConstraints() const { return CaseConstraints; } 407 const ConstraintSet &getArgConstraints() const { return ArgConstraints; } 408 409 QualType getArgType(ArgNo ArgN) const { 410 return StdLibraryFunctionsChecker::getArgType(FD, ArgN); 411 } 412 413 // Returns true if the summary should be applied to the given function. 414 // And if yes then store the function declaration. 415 bool matchesAndSet(const FunctionDecl *FD) { 416 bool Result = Sign.matches(FD) && validateByConstraints(FD); 417 if (Result) { 418 assert(!this->FD && "FD must not be set more than once"); 419 this->FD = FD; 420 } 421 return Result; 422 } 423 424 private: 425 // Once we know the exact type of the function then do sanity check on all 426 // the given constraints. 427 bool validateByConstraints(const FunctionDecl *FD) const { 428 for (const ConstraintSet &Case : CaseConstraints) 429 for (const ValueConstraintPtr &Constraint : Case) 430 if (!Constraint->checkValidity(FD)) 431 return false; 432 for (const ValueConstraintPtr &Constraint : ArgConstraints) 433 if (!Constraint->checkValidity(FD)) 434 return false; 435 return true; 436 } 437 }; 438 439 // The map of all functions supported by the checker. It is initialized 440 // lazily, and it doesn't change after initialization. 441 using FunctionSummaryMapType = llvm::DenseMap<const FunctionDecl *, Summary>; 442 mutable FunctionSummaryMapType FunctionSummaryMap; 443 444 mutable std::unique_ptr<BugType> BT_InvalidArg; 445 446 static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) { 447 return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN); 448 } 449 450 public: 451 void checkPreCall(const CallEvent &Call, CheckerContext &C) const; 452 void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 453 bool evalCall(const CallEvent &Call, CheckerContext &C) const; 454 455 enum CheckKind { 456 CK_StdCLibraryFunctionArgsChecker, 457 CK_StdCLibraryFunctionsTesterChecker, 458 CK_NumCheckKinds 459 }; 460 DefaultBool ChecksEnabled[CK_NumCheckKinds]; 461 CheckerNameRef CheckNames[CK_NumCheckKinds]; 462 463 bool DisplayLoadedSummaries = false; 464 465 private: 466 Optional<Summary> findFunctionSummary(const FunctionDecl *FD, 467 CheckerContext &C) const; 468 Optional<Summary> findFunctionSummary(const CallEvent &Call, 469 CheckerContext &C) const; 470 471 void initFunctionSummaries(CheckerContext &C) const; 472 473 void reportBug(const CallEvent &Call, ExplodedNode *N, 474 CheckerContext &C) const { 475 if (!ChecksEnabled[CK_StdCLibraryFunctionArgsChecker]) 476 return; 477 // TODO Add detailed diagnostic. 478 StringRef Msg = "Function argument constraint is not satisfied"; 479 if (!BT_InvalidArg) 480 BT_InvalidArg = std::make_unique<BugType>( 481 CheckNames[CK_StdCLibraryFunctionArgsChecker], 482 "Unsatisfied argument constraints", categories::LogicError); 483 auto R = std::make_unique<PathSensitiveBugReport>(*BT_InvalidArg, Msg, N); 484 bugreporter::trackExpressionValue(N, Call.getArgExpr(0), *R); 485 C.emitReport(std::move(R)); 486 } 487 }; 488 489 const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret = 490 std::numeric_limits<ArgNo>::max(); 491 492 } // end of anonymous namespace 493 494 ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsOutOfRange( 495 ProgramStateRef State, const CallEvent &Call, 496 const Summary &Summary) const { 497 498 ProgramStateManager &Mgr = State->getStateManager(); 499 SValBuilder &SVB = Mgr.getSValBuilder(); 500 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 501 ConstraintManager &CM = Mgr.getConstraintManager(); 502 QualType T = Summary.getArgType(getArgNo()); 503 SVal V = getArgSVal(Call, getArgNo()); 504 505 if (auto N = V.getAs<NonLoc>()) { 506 const IntRangeVector &R = getRanges(); 507 size_t E = R.size(); 508 for (size_t I = 0; I != E; ++I) { 509 const llvm::APSInt &Min = BVF.getValue(R[I].first, T); 510 const llvm::APSInt &Max = BVF.getValue(R[I].second, T); 511 assert(Min <= Max); 512 State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 513 if (!State) 514 break; 515 } 516 } 517 518 return State; 519 } 520 521 ProgramStateRef StdLibraryFunctionsChecker::RangeConstraint::applyAsWithinRange( 522 ProgramStateRef State, const CallEvent &Call, 523 const Summary &Summary) const { 524 525 ProgramStateManager &Mgr = State->getStateManager(); 526 SValBuilder &SVB = Mgr.getSValBuilder(); 527 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 528 ConstraintManager &CM = Mgr.getConstraintManager(); 529 QualType T = Summary.getArgType(getArgNo()); 530 SVal V = getArgSVal(Call, getArgNo()); 531 532 // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R". 533 // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary, 534 // and then cut away all holes in R one by one. 535 // 536 // E.g. consider a range list R as [A, B] and [C, D] 537 // -------+--------+------------------+------------+-----------> 538 // A B C D 539 // Then we assume that the value is not in [-inf, A - 1], 540 // then not in [D + 1, +inf], then not in [B + 1, C - 1] 541 if (auto N = V.getAs<NonLoc>()) { 542 const IntRangeVector &R = getRanges(); 543 size_t E = R.size(); 544 545 const llvm::APSInt &MinusInf = BVF.getMinValue(T); 546 const llvm::APSInt &PlusInf = BVF.getMaxValue(T); 547 548 const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T); 549 if (Left != PlusInf) { 550 assert(MinusInf <= Left); 551 State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false); 552 if (!State) 553 return nullptr; 554 } 555 556 const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T); 557 if (Right != MinusInf) { 558 assert(Right <= PlusInf); 559 State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false); 560 if (!State) 561 return nullptr; 562 } 563 564 for (size_t I = 1; I != E; ++I) { 565 const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T); 566 const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T); 567 if (Min <= Max) { 568 State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 569 if (!State) 570 return nullptr; 571 } 572 } 573 } 574 575 return State; 576 } 577 578 ProgramStateRef StdLibraryFunctionsChecker::ComparisonConstraint::apply( 579 ProgramStateRef State, const CallEvent &Call, const Summary &Summary, 580 CheckerContext &C) const { 581 582 ProgramStateManager &Mgr = State->getStateManager(); 583 SValBuilder &SVB = Mgr.getSValBuilder(); 584 QualType CondT = SVB.getConditionType(); 585 QualType T = Summary.getArgType(getArgNo()); 586 SVal V = getArgSVal(Call, getArgNo()); 587 588 BinaryOperator::Opcode Op = getOpcode(); 589 ArgNo OtherArg = getOtherArgNo(); 590 SVal OtherV = getArgSVal(Call, OtherArg); 591 QualType OtherT = Summary.getArgType(OtherArg); 592 // Note: we avoid integral promotion for comparison. 593 OtherV = SVB.evalCast(OtherV, T, OtherT); 594 if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT) 595 .getAs<DefinedOrUnknownSVal>()) 596 State = State->assume(*CompV, true); 597 return State; 598 } 599 600 void StdLibraryFunctionsChecker::checkPreCall(const CallEvent &Call, 601 CheckerContext &C) const { 602 Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 603 if (!FoundSummary) 604 return; 605 606 const Summary &Summary = *FoundSummary; 607 ProgramStateRef State = C.getState(); 608 609 ProgramStateRef NewState = State; 610 for (const ValueConstraintPtr &Constraint : Summary.getArgConstraints()) { 611 ProgramStateRef SuccessSt = Constraint->apply(NewState, Call, Summary, C); 612 ProgramStateRef FailureSt = 613 Constraint->negate()->apply(NewState, Call, Summary, C); 614 // The argument constraint is not satisfied. 615 if (FailureSt && !SuccessSt) { 616 if (ExplodedNode *N = C.generateErrorNode(NewState)) 617 reportBug(Call, N, C); 618 break; 619 } else { 620 // We will apply the constraint even if we cannot reason about the 621 // argument. This means both SuccessSt and FailureSt can be true. If we 622 // weren't applying the constraint that would mean that symbolic 623 // execution continues on a code whose behaviour is undefined. 624 assert(SuccessSt); 625 NewState = SuccessSt; 626 } 627 } 628 if (NewState && NewState != State) 629 C.addTransition(NewState); 630 } 631 632 void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call, 633 CheckerContext &C) const { 634 Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 635 if (!FoundSummary) 636 return; 637 638 // Now apply the constraints. 639 const Summary &Summary = *FoundSummary; 640 ProgramStateRef State = C.getState(); 641 642 // Apply case/branch specifications. 643 for (const ConstraintSet &Case : Summary.getCaseConstraints()) { 644 ProgramStateRef NewState = State; 645 for (const ValueConstraintPtr &Constraint : Case) { 646 NewState = Constraint->apply(NewState, Call, Summary, C); 647 if (!NewState) 648 break; 649 } 650 651 if (NewState && NewState != State) 652 C.addTransition(NewState); 653 } 654 } 655 656 bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call, 657 CheckerContext &C) const { 658 Optional<Summary> FoundSummary = findFunctionSummary(Call, C); 659 if (!FoundSummary) 660 return false; 661 662 const Summary &Summary = *FoundSummary; 663 switch (Summary.getInvalidationKd()) { 664 case EvalCallAsPure: { 665 ProgramStateRef State = C.getState(); 666 const LocationContext *LC = C.getLocationContext(); 667 const auto *CE = cast_or_null<CallExpr>(Call.getOriginExpr()); 668 SVal V = C.getSValBuilder().conjureSymbolVal( 669 CE, LC, CE->getType().getCanonicalType(), C.blockCount()); 670 State = State->BindExpr(CE, LC, V); 671 C.addTransition(State); 672 return true; 673 } 674 case NoEvalCall: 675 // Summary tells us to avoid performing eval::Call. The function is possibly 676 // evaluated by another checker, or evaluated conservatively. 677 return false; 678 } 679 llvm_unreachable("Unknown invalidation kind!"); 680 } 681 682 bool StdLibraryFunctionsChecker::Signature::matches( 683 const FunctionDecl *FD) const { 684 // Check number of arguments: 685 if (FD->param_size() != ArgTys.size()) 686 return false; 687 688 // Check return type. 689 if (!isIrrelevant(RetTy)) 690 if (RetTy != FD->getReturnType().getCanonicalType()) 691 return false; 692 693 // Check argument types. 694 for (size_t I = 0, E = ArgTys.size(); I != E; ++I) { 695 QualType ArgTy = ArgTys[I]; 696 if (isIrrelevant(ArgTy)) 697 continue; 698 if (ArgTy != FD->getParamDecl(I)->getType().getCanonicalType()) 699 return false; 700 } 701 702 return true; 703 } 704 705 Optional<StdLibraryFunctionsChecker::Summary> 706 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD, 707 CheckerContext &C) const { 708 if (!FD) 709 return None; 710 711 initFunctionSummaries(C); 712 713 auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl()); 714 if (FSMI == FunctionSummaryMap.end()) 715 return None; 716 return FSMI->second; 717 } 718 719 Optional<StdLibraryFunctionsChecker::Summary> 720 StdLibraryFunctionsChecker::findFunctionSummary(const CallEvent &Call, 721 CheckerContext &C) const { 722 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); 723 if (!FD) 724 return None; 725 return findFunctionSummary(FD, C); 726 } 727 728 void StdLibraryFunctionsChecker::initFunctionSummaries( 729 CheckerContext &C) const { 730 if (!FunctionSummaryMap.empty()) 731 return; 732 733 SValBuilder &SVB = C.getSValBuilder(); 734 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 735 const ASTContext &ACtx = BVF.getContext(); 736 737 // These types are useful for writing specifications quickly, 738 // New specifications should probably introduce more types. 739 // Some types are hard to obtain from the AST, eg. "ssize_t". 740 // In such cases it should be possible to provide multiple variants 741 // of function summary for common cases (eg. ssize_t could be int or long 742 // or long long, so three summary variants would be enough). 743 // Of course, function variants are also useful for C++ overloads. 744 const QualType IntTy = ACtx.IntTy; 745 const QualType LongTy = ACtx.LongTy; 746 const QualType LongLongTy = ACtx.LongLongTy; 747 const QualType SizeTy = ACtx.getSizeType(); 748 const QualType VoidPtrTy = ACtx.VoidPtrTy; // void * 749 const QualType VoidPtrRestrictTy = 750 ACtx.getRestrictType(VoidPtrTy); // void *restrict 751 const QualType ConstVoidPtrTy = 752 ACtx.getPointerType(ACtx.VoidTy.withConst()); // const void * 753 const QualType ConstCharPtrTy = 754 ACtx.getPointerType(ACtx.CharTy.withConst()); // const char * 755 const QualType ConstVoidPtrRestrictTy = 756 ACtx.getRestrictType(ConstVoidPtrTy); // const void *restrict 757 758 const RangeInt IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); 759 const RangeInt LongMax = BVF.getMaxValue(LongTy).getLimitedValue(); 760 const RangeInt LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue(); 761 762 // Set UCharRangeMax to min of int or uchar maximum value. 763 // The C standard states that the arguments of functions like isalpha must 764 // be representable as an unsigned char. Their type is 'int', so the max 765 // value of the argument should be min(UCharMax, IntMax). This just happen 766 // to be true for commonly used and well tested instruction set 767 // architectures, but not for others. 768 const RangeInt UCharRangeMax = 769 std::min(BVF.getMaxValue(ACtx.UnsignedCharTy).getLimitedValue(), IntMax); 770 771 // The platform dependent value of EOF. 772 // Try our best to parse this from the Preprocessor, otherwise fallback to -1. 773 const auto EOFv = [&C]() -> RangeInt { 774 if (const llvm::Optional<int> OptInt = 775 tryExpandAsInteger("EOF", C.getPreprocessor())) 776 return *OptInt; 777 return -1; 778 }(); 779 780 // Auxiliary class to aid adding summaries to the summary map. 781 struct AddToFunctionSummaryMap { 782 const ASTContext &ACtx; 783 FunctionSummaryMapType ⤅ 784 bool DisplayLoadedSummaries; 785 AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM, 786 bool DisplayLoadedSummaries) 787 : ACtx(ACtx), Map(FSM), DisplayLoadedSummaries(DisplayLoadedSummaries) { 788 } 789 790 // Add a summary to a FunctionDecl found by lookup. The lookup is performed 791 // by the given Name, and in the global scope. The summary will be attached 792 // to the found FunctionDecl only if the signatures match. 793 void operator()(StringRef Name, Summary S) { 794 IdentifierInfo &II = ACtx.Idents.get(Name); 795 auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); 796 if (LookupRes.size() == 0) 797 return; 798 for (Decl *D : LookupRes) { 799 if (auto *FD = dyn_cast<FunctionDecl>(D)) { 800 if (S.matchesAndSet(FD)) { 801 auto Res = Map.insert({FD->getCanonicalDecl(), S}); 802 assert(Res.second && "Function already has a summary set!"); 803 (void)Res; 804 if (DisplayLoadedSummaries) { 805 llvm::errs() << "Loaded summary for: "; 806 FD->print(llvm::errs()); 807 llvm::errs() << "\n"; 808 } 809 return; 810 } 811 } 812 } 813 } 814 // Add several summaries for the given name. 815 void operator()(StringRef Name, const std::vector<Summary> &Summaries) { 816 for (const Summary &S : Summaries) 817 operator()(Name, S); 818 } 819 } addToFunctionSummaryMap(ACtx, FunctionSummaryMap, DisplayLoadedSummaries); 820 821 // We are finally ready to define specifications for all supported functions. 822 // 823 // The signature needs to have the correct number of arguments. 824 // However, we insert `Irrelevant' when the type is insignificant. 825 // 826 // Argument ranges should always cover all variants. If return value 827 // is completely unknown, omit it from the respective range set. 828 // 829 // All types in the spec need to be canonical. 830 // 831 // Every item in the list of range sets represents a particular 832 // execution path the analyzer would need to explore once 833 // the call is modeled - a new program state is constructed 834 // for every range set, and each range line in the range set 835 // corresponds to a specific constraint within this state. 836 // 837 // Upon comparing to another argument, the other argument is casted 838 // to the current argument's type. This avoids proper promotion but 839 // seems useful. For example, read() receives size_t argument, 840 // and its return value, which is of type ssize_t, cannot be greater 841 // than this argument. If we made a promotion, and the size argument 842 // is equal to, say, 10, then we'd impose a range of [0, 10] on the 843 // return value, however the correct range is [-1, 10]. 844 // 845 // Please update the list of functions in the header after editing! 846 847 // Below are helpers functions to create the summaries. 848 auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind, 849 IntRangeVector Ranges) { 850 return std::make_shared<RangeConstraint>(ArgN, Kind, Ranges); 851 }; 852 auto BufferSize = [](auto... Args) { 853 return std::make_shared<BufferSizeConstraint>(Args...); 854 }; 855 struct { 856 auto operator()(RangeKind Kind, IntRangeVector Ranges) { 857 return std::make_shared<RangeConstraint>(Ret, Kind, Ranges); 858 } 859 auto operator()(BinaryOperator::Opcode Op, ArgNo OtherArgN) { 860 return std::make_shared<ComparisonConstraint>(Ret, Op, OtherArgN); 861 } 862 } ReturnValueCondition; 863 auto Range = [](RangeInt b, RangeInt e) { 864 return IntRangeVector{std::pair<RangeInt, RangeInt>{b, e}}; 865 }; 866 auto SingleValue = [](RangeInt v) { 867 return IntRangeVector{std::pair<RangeInt, RangeInt>{v, v}}; 868 }; 869 auto LessThanOrEq = BO_LE; 870 auto NotNull = [&](ArgNo ArgN) { 871 return std::make_shared<NotNullConstraint>(ArgN); 872 }; 873 874 using RetType = QualType; 875 // Templates for summaries that are reused by many functions. 876 auto Getc = [&]() { 877 return Summary(ArgTypes{Irrelevant}, RetType{IntTy}, NoEvalCall) 878 .Case({ReturnValueCondition(WithinRange, 879 {{EOFv, EOFv}, {0, UCharRangeMax}})}); 880 }; 881 auto Read = [&](RetType R, RangeInt Max) { 882 return Summary(ArgTypes{Irrelevant, Irrelevant, SizeTy}, RetType{R}, 883 NoEvalCall) 884 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 885 ReturnValueCondition(WithinRange, Range(-1, Max))}); 886 }; 887 auto Fread = [&]() { 888 return Summary(ArgTypes{VoidPtrRestrictTy, Irrelevant, SizeTy, Irrelevant}, 889 RetType{SizeTy}, NoEvalCall) 890 .Case({ 891 ReturnValueCondition(LessThanOrEq, ArgNo(2)), 892 }) 893 .ArgConstraint(NotNull(ArgNo(0))); 894 }; 895 auto Fwrite = [&]() { 896 return Summary( 897 ArgTypes{ConstVoidPtrRestrictTy, Irrelevant, SizeTy, Irrelevant}, 898 RetType{SizeTy}, NoEvalCall) 899 .Case({ 900 ReturnValueCondition(LessThanOrEq, ArgNo(2)), 901 }) 902 .ArgConstraint(NotNull(ArgNo(0))); 903 }; 904 auto Getline = [&](RetType R, RangeInt Max) { 905 return Summary(ArgTypes{Irrelevant, Irrelevant, Irrelevant}, RetType{R}, 906 NoEvalCall) 907 .Case({ReturnValueCondition(WithinRange, {{-1, -1}, {1, Max}})}); 908 }; 909 910 // The isascii() family of functions. 911 // The behavior is undefined if the value of the argument is not 912 // representable as unsigned char or is not equal to EOF. See e.g. C99 913 // 7.4.1.2 The isalpha function (p: 181-182). 914 addToFunctionSummaryMap( 915 "isalnum", 916 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 917 // Boils down to isupper() or islower() or isdigit(). 918 .Case({ArgumentCondition(0U, WithinRange, 919 {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}), 920 ReturnValueCondition(OutOfRange, SingleValue(0))}) 921 // The locale-specific range. 922 // No post-condition. We are completely unaware of 923 // locale-specific return values. 924 .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 925 .Case( 926 {ArgumentCondition( 927 0U, OutOfRange, 928 {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), 929 ReturnValueCondition(WithinRange, SingleValue(0))}) 930 .ArgConstraint(ArgumentCondition( 931 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); 932 addToFunctionSummaryMap( 933 "isalpha", 934 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 935 .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}), 936 ReturnValueCondition(OutOfRange, SingleValue(0))}) 937 // The locale-specific range. 938 .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 939 .Case({ArgumentCondition( 940 0U, OutOfRange, 941 {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), 942 ReturnValueCondition(WithinRange, SingleValue(0))})); 943 addToFunctionSummaryMap( 944 "isascii", 945 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 946 .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), 947 ReturnValueCondition(OutOfRange, SingleValue(0))}) 948 .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)), 949 ReturnValueCondition(WithinRange, SingleValue(0))})); 950 addToFunctionSummaryMap( 951 "isblank", 952 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 953 .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}), 954 ReturnValueCondition(OutOfRange, SingleValue(0))}) 955 .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}), 956 ReturnValueCondition(WithinRange, SingleValue(0))})); 957 addToFunctionSummaryMap( 958 "iscntrl", 959 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 960 .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}), 961 ReturnValueCondition(OutOfRange, SingleValue(0))}) 962 .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}), 963 ReturnValueCondition(WithinRange, SingleValue(0))})); 964 addToFunctionSummaryMap( 965 "isdigit", 966 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 967 .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')), 968 ReturnValueCondition(OutOfRange, SingleValue(0))}) 969 .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')), 970 ReturnValueCondition(WithinRange, SingleValue(0))})); 971 addToFunctionSummaryMap( 972 "isgraph", 973 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 974 .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)), 975 ReturnValueCondition(OutOfRange, SingleValue(0))}) 976 .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)), 977 ReturnValueCondition(WithinRange, SingleValue(0))})); 978 addToFunctionSummaryMap( 979 "islower", 980 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 981 // Is certainly lowercase. 982 .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')), 983 ReturnValueCondition(OutOfRange, SingleValue(0))}) 984 // Is ascii but not lowercase. 985 .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), 986 ArgumentCondition(0U, OutOfRange, Range('a', 'z')), 987 ReturnValueCondition(WithinRange, SingleValue(0))}) 988 // The locale-specific range. 989 .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 990 // Is not an unsigned char. 991 .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)), 992 ReturnValueCondition(WithinRange, SingleValue(0))})); 993 addToFunctionSummaryMap( 994 "isprint", 995 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 996 .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)), 997 ReturnValueCondition(OutOfRange, SingleValue(0))}) 998 .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)), 999 ReturnValueCondition(WithinRange, SingleValue(0))})); 1000 addToFunctionSummaryMap( 1001 "ispunct", 1002 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 1003 .Case({ArgumentCondition( 1004 0U, WithinRange, 1005 {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), 1006 ReturnValueCondition(OutOfRange, SingleValue(0))}) 1007 .Case({ArgumentCondition( 1008 0U, OutOfRange, 1009 {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), 1010 ReturnValueCondition(WithinRange, SingleValue(0))})); 1011 addToFunctionSummaryMap( 1012 "isspace", 1013 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 1014 // Space, '\f', '\n', '\r', '\t', '\v'. 1015 .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}), 1016 ReturnValueCondition(OutOfRange, SingleValue(0))}) 1017 // The locale-specific range. 1018 .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 1019 .Case({ArgumentCondition(0U, OutOfRange, 1020 {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}), 1021 ReturnValueCondition(WithinRange, SingleValue(0))})); 1022 addToFunctionSummaryMap( 1023 "isupper", 1024 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 1025 // Is certainly uppercase. 1026 .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')), 1027 ReturnValueCondition(OutOfRange, SingleValue(0))}) 1028 // The locale-specific range. 1029 .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) 1030 // Other. 1031 .Case({ArgumentCondition(0U, OutOfRange, 1032 {{'A', 'Z'}, {128, UCharRangeMax}}), 1033 ReturnValueCondition(WithinRange, SingleValue(0))})); 1034 addToFunctionSummaryMap( 1035 "isxdigit", 1036 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 1037 .Case({ArgumentCondition(0U, WithinRange, 1038 {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), 1039 ReturnValueCondition(OutOfRange, SingleValue(0))}) 1040 .Case({ArgumentCondition(0U, OutOfRange, 1041 {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), 1042 ReturnValueCondition(WithinRange, SingleValue(0))})); 1043 1044 // The getc() family of functions that returns either a char or an EOF. 1045 addToFunctionSummaryMap("getc", Getc()); 1046 addToFunctionSummaryMap("fgetc", Getc()); 1047 addToFunctionSummaryMap( 1048 "getchar", Summary(ArgTypes{}, RetType{IntTy}, NoEvalCall) 1049 .Case({ReturnValueCondition( 1050 WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})})); 1051 1052 // read()-like functions that never return more than buffer size. 1053 // We are not sure how ssize_t is defined on every platform, so we 1054 // provide three variants that should cover common cases. 1055 addToFunctionSummaryMap("read", {Read(IntTy, IntMax), Read(LongTy, LongMax), 1056 Read(LongLongTy, LongLongMax)}); 1057 addToFunctionSummaryMap("write", {Read(IntTy, IntMax), Read(LongTy, LongMax), 1058 Read(LongLongTy, LongLongMax)}); 1059 addToFunctionSummaryMap("fread", Fread()); 1060 addToFunctionSummaryMap("fwrite", Fwrite()); 1061 // getline()-like functions either fail or read at least the delimiter. 1062 addToFunctionSummaryMap("getline", 1063 {Getline(IntTy, IntMax), Getline(LongTy, LongMax), 1064 Getline(LongLongTy, LongLongMax)}); 1065 addToFunctionSummaryMap("getdelim", 1066 {Getline(IntTy, IntMax), Getline(LongTy, LongMax), 1067 Getline(LongLongTy, LongLongMax)}); 1068 1069 // Functions for testing. 1070 if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) { 1071 addToFunctionSummaryMap( 1072 "__two_constrained_args", 1073 Summary(ArgTypes{IntTy, IntTy}, RetType{IntTy}, EvalCallAsPure) 1074 .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))) 1075 .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1)))); 1076 addToFunctionSummaryMap( 1077 "__arg_constrained_twice", 1078 Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) 1079 .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))) 1080 .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2)))); 1081 addToFunctionSummaryMap( 1082 "__defaultparam", 1083 Summary(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}, EvalCallAsPure) 1084 .ArgConstraint(NotNull(ArgNo(0)))); 1085 addToFunctionSummaryMap("__variadic", 1086 Summary(ArgTypes{VoidPtrTy, ConstCharPtrTy}, 1087 RetType{IntTy}, EvalCallAsPure) 1088 .ArgConstraint(NotNull(ArgNo(0))) 1089 .ArgConstraint(NotNull(ArgNo(1)))); 1090 addToFunctionSummaryMap( 1091 "__buf_size_arg_constraint", 1092 Summary(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}, 1093 EvalCallAsPure) 1094 .ArgConstraint( 1095 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))); 1096 addToFunctionSummaryMap( 1097 "__buf_size_arg_constraint_mul", 1098 Summary(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}, 1099 EvalCallAsPure) 1100 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), 1101 /*BufSizeMultiplier=*/ArgNo(2)))); 1102 } 1103 } 1104 1105 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) { 1106 auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>(); 1107 Checker->DisplayLoadedSummaries = 1108 mgr.getAnalyzerOptions().getCheckerBooleanOption( 1109 Checker, "DisplayLoadedSummaries"); 1110 } 1111 1112 bool ento::shouldRegisterStdCLibraryFunctionsChecker(const CheckerManager &mgr) { 1113 return true; 1114 } 1115 1116 #define REGISTER_CHECKER(name) \ 1117 void ento::register##name(CheckerManager &mgr) { \ 1118 StdLibraryFunctionsChecker *checker = \ 1119 mgr.getChecker<StdLibraryFunctionsChecker>(); \ 1120 checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true; \ 1121 checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] = \ 1122 mgr.getCurrentCheckerName(); \ 1123 } \ 1124 \ 1125 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } 1126 1127 REGISTER_CHECKER(StdCLibraryFunctionArgsChecker) 1128 REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker) 1129