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 virtual 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 // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect 1908 addToFunctionSummaryMap( 1909 "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1910 Summary(NoEvalCall) 1911 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 1912 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1913 .ArgConstraint(NotNull(ArgNo(0)))); 1914 1915 // int mkdirat(int dirfd, const char *pathname, mode_t mode); 1916 // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect 1917 addToFunctionSummaryMap( 1918 "mkdirat", 1919 Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1920 Summary(NoEvalCall) 1921 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 1922 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1923 .ArgConstraint(NotNull(ArgNo(1)))); 1924 1925 Optional<QualType> Dev_tTy = lookupTy("dev_t"); 1926 1927 // int mknod(const char *pathname, mode_t mode, dev_t dev); 1928 // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect 1929 addToFunctionSummaryMap( 1930 "mknod", 1931 Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}), 1932 Summary(NoEvalCall) 1933 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 1934 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1935 .ArgConstraint(NotNull(ArgNo(0)))); 1936 1937 // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev); 1938 // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect 1939 addToFunctionSummaryMap( 1940 "mknodat", 1941 Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy}, 1942 RetType{IntTy}), 1943 Summary(NoEvalCall) 1944 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 1945 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1946 .ArgConstraint(NotNull(ArgNo(1)))); 1947 1948 // int chmod(const char *path, mode_t mode); 1949 addToFunctionSummaryMap( 1950 "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}), 1951 Summary(NoEvalCall) 1952 .Case(ReturnsZero, ErrnoMustNotBeChecked) 1953 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1954 .ArgConstraint(NotNull(ArgNo(0)))); 1955 1956 // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags); 1957 addToFunctionSummaryMap( 1958 "fchmodat", 1959 Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy}, 1960 RetType{IntTy}), 1961 Summary(NoEvalCall) 1962 .Case(ReturnsZero, ErrnoMustNotBeChecked) 1963 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1964 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1965 .ArgConstraint(NotNull(ArgNo(1)))); 1966 1967 // int fchmod(int fildes, mode_t mode); 1968 addToFunctionSummaryMap( 1969 "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}), 1970 Summary(NoEvalCall) 1971 .Case(ReturnsZero, ErrnoMustNotBeChecked) 1972 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1973 .ArgConstraint( 1974 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 1975 1976 Optional<QualType> Uid_tTy = lookupTy("uid_t"); 1977 Optional<QualType> Gid_tTy = lookupTy("gid_t"); 1978 1979 // int fchownat(int dirfd, const char *pathname, uid_t owner, gid_t group, 1980 // int flags); 1981 addToFunctionSummaryMap( 1982 "fchownat", 1983 Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy}, 1984 RetType{IntTy}), 1985 Summary(NoEvalCall) 1986 .Case(ReturnsZero, ErrnoMustNotBeChecked) 1987 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1988 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 1989 .ArgConstraint(NotNull(ArgNo(1)))); 1990 1991 // int chown(const char *path, uid_t owner, gid_t group); 1992 addToFunctionSummaryMap( 1993 "chown", 1994 Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 1995 Summary(NoEvalCall) 1996 .Case(ReturnsZero, ErrnoMustNotBeChecked) 1997 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 1998 .ArgConstraint(NotNull(ArgNo(0)))); 1999 2000 // int lchown(const char *path, uid_t owner, gid_t group); 2001 addToFunctionSummaryMap( 2002 "lchown", 2003 Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 2004 Summary(NoEvalCall) 2005 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2006 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2007 .ArgConstraint(NotNull(ArgNo(0)))); 2008 2009 // int fchown(int fildes, uid_t owner, gid_t group); 2010 addToFunctionSummaryMap( 2011 "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}), 2012 Summary(NoEvalCall) 2013 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2014 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2015 .ArgConstraint( 2016 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2017 2018 // int rmdir(const char *pathname); 2019 addToFunctionSummaryMap("rmdir", 2020 Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 2021 Summary(NoEvalCall) 2022 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2023 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2024 .ArgConstraint(NotNull(ArgNo(0)))); 2025 2026 // int chdir(const char *path); 2027 addToFunctionSummaryMap("chdir", 2028 Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 2029 Summary(NoEvalCall) 2030 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2031 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2032 .ArgConstraint(NotNull(ArgNo(0)))); 2033 2034 // int link(const char *oldpath, const char *newpath); 2035 addToFunctionSummaryMap( 2036 "link", 2037 Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}), 2038 Summary(NoEvalCall) 2039 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2040 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2041 .ArgConstraint(NotNull(ArgNo(0))) 2042 .ArgConstraint(NotNull(ArgNo(1)))); 2043 2044 // int linkat(int fd1, const char *path1, int fd2, const char *path2, 2045 // int flag); 2046 addToFunctionSummaryMap( 2047 "linkat", 2048 Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy}, 2049 RetType{IntTy}), 2050 Summary(NoEvalCall) 2051 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2052 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2053 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2054 .ArgConstraint(NotNull(ArgNo(1))) 2055 .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax))) 2056 .ArgConstraint(NotNull(ArgNo(3)))); 2057 2058 // int unlink(const char *pathname); 2059 addToFunctionSummaryMap("unlink", 2060 Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}), 2061 Summary(NoEvalCall) 2062 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2063 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2064 .ArgConstraint(NotNull(ArgNo(0)))); 2065 2066 // int unlinkat(int fd, const char *path, int flag); 2067 addToFunctionSummaryMap( 2068 "unlinkat", 2069 Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}), 2070 Summary(NoEvalCall) 2071 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2072 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2073 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2074 .ArgConstraint(NotNull(ArgNo(1)))); 2075 2076 Optional<QualType> StructStatTy = lookupTy("stat"); 2077 Optional<QualType> StructStatPtrTy = getPointerTy(StructStatTy); 2078 Optional<QualType> StructStatPtrRestrictTy = getRestrictTy(StructStatPtrTy); 2079 2080 // int fstat(int fd, struct stat *statbuf); 2081 addToFunctionSummaryMap( 2082 "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}), 2083 Summary(NoEvalCall) 2084 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2085 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2086 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2087 .ArgConstraint(NotNull(ArgNo(1)))); 2088 2089 // int stat(const char *restrict path, struct stat *restrict buf); 2090 addToFunctionSummaryMap( 2091 "stat", 2092 Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy}, 2093 RetType{IntTy}), 2094 Summary(NoEvalCall) 2095 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2096 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2097 .ArgConstraint(NotNull(ArgNo(0))) 2098 .ArgConstraint(NotNull(ArgNo(1)))); 2099 2100 // int lstat(const char *restrict path, struct stat *restrict buf); 2101 addToFunctionSummaryMap( 2102 "lstat", 2103 Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy}, 2104 RetType{IntTy}), 2105 Summary(NoEvalCall) 2106 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2107 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2108 .ArgConstraint(NotNull(ArgNo(0))) 2109 .ArgConstraint(NotNull(ArgNo(1)))); 2110 2111 // int fstatat(int fd, const char *restrict path, 2112 // struct stat *restrict buf, int flag); 2113 addToFunctionSummaryMap( 2114 "fstatat", 2115 Signature(ArgTypes{IntTy, ConstCharPtrRestrictTy, 2116 StructStatPtrRestrictTy, IntTy}, 2117 RetType{IntTy}), 2118 Summary(NoEvalCall) 2119 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2120 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2121 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2122 .ArgConstraint(NotNull(ArgNo(1))) 2123 .ArgConstraint(NotNull(ArgNo(2)))); 2124 2125 // DIR *opendir(const char *name); 2126 // FIXME: Improve for errno modeling. 2127 addToFunctionSummaryMap( 2128 "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}), 2129 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2130 2131 // DIR *fdopendir(int fd); 2132 // FIXME: Improve for errno modeling. 2133 addToFunctionSummaryMap("fdopendir", 2134 Signature(ArgTypes{IntTy}, RetType{DirPtrTy}), 2135 Summary(NoEvalCall) 2136 .ArgConstraint(ArgumentCondition( 2137 0, WithinRange, Range(0, IntMax)))); 2138 2139 // int isatty(int fildes); 2140 addToFunctionSummaryMap( 2141 "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2142 Summary(NoEvalCall) 2143 .Case({ReturnValueCondition(WithinRange, Range(0, 1))}, 2144 ErrnoIrrelevant) 2145 .ArgConstraint( 2146 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2147 2148 // FILE *popen(const char *command, const char *type); 2149 // FIXME: Improve for errno modeling. 2150 addToFunctionSummaryMap( 2151 "popen", 2152 Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}), 2153 Summary(NoEvalCall) 2154 .ArgConstraint(NotNull(ArgNo(0))) 2155 .ArgConstraint(NotNull(ArgNo(1)))); 2156 2157 // int pclose(FILE *stream); 2158 // FIXME: Improve for errno modeling. 2159 addToFunctionSummaryMap( 2160 "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), 2161 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2162 2163 // int close(int fildes); 2164 addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2165 Summary(NoEvalCall) 2166 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2167 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2168 .ArgConstraint(ArgumentCondition( 2169 0, WithinRange, Range(-1, IntMax)))); 2170 2171 // long fpathconf(int fildes, int name); 2172 addToFunctionSummaryMap("fpathconf", 2173 Signature(ArgTypes{IntTy, IntTy}, RetType{LongTy}), 2174 Summary(NoEvalCall) 2175 .ArgConstraint(ArgumentCondition( 2176 0, WithinRange, Range(0, IntMax)))); 2177 2178 // long pathconf(const char *path, int name); 2179 addToFunctionSummaryMap( 2180 "pathconf", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{LongTy}), 2181 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2182 2183 // FILE *fdopen(int fd, const char *mode); 2184 // FIXME: Improve for errno modeling. 2185 addToFunctionSummaryMap( 2186 "fdopen", 2187 Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}), 2188 Summary(NoEvalCall) 2189 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2190 .ArgConstraint(NotNull(ArgNo(1)))); 2191 2192 // void rewinddir(DIR *dir); 2193 addToFunctionSummaryMap( 2194 "rewinddir", Signature(ArgTypes{DirPtrTy}, RetType{VoidTy}), 2195 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2196 2197 // void seekdir(DIR *dirp, long loc); 2198 addToFunctionSummaryMap( 2199 "seekdir", Signature(ArgTypes{DirPtrTy, LongTy}, RetType{VoidTy}), 2200 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2201 2202 // int rand_r(unsigned int *seedp); 2203 addToFunctionSummaryMap( 2204 "rand_r", Signature(ArgTypes{UnsignedIntPtrTy}, RetType{IntTy}), 2205 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2206 2207 // int fileno(FILE *stream); 2208 addToFunctionSummaryMap( 2209 "fileno", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}), 2210 Summary(NoEvalCall) 2211 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 2212 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2213 .ArgConstraint(NotNull(ArgNo(0)))); 2214 2215 // int fseeko(FILE *stream, off_t offset, int whence); 2216 addToFunctionSummaryMap( 2217 "fseeko", 2218 Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}), 2219 Summary(NoEvalCall) 2220 .Case(ReturnsZeroOrMinusOne, ErrnoIrrelevant) 2221 .ArgConstraint(NotNull(ArgNo(0)))); 2222 2223 // off_t ftello(FILE *stream); 2224 addToFunctionSummaryMap( 2225 "ftello", Signature(ArgTypes{FilePtrTy}, RetType{Off_tTy}), 2226 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2227 2228 // void *mmap(void *addr, size_t length, int prot, int flags, int fd, 2229 // off_t offset); 2230 // FIXME: Improve for errno modeling. 2231 addToFunctionSummaryMap( 2232 "mmap", 2233 Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy}, 2234 RetType{VoidPtrTy}), 2235 Summary(NoEvalCall) 2236 .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) 2237 .ArgConstraint( 2238 ArgumentCondition(4, WithinRange, Range(-1, IntMax)))); 2239 2240 Optional<QualType> Off64_tTy = lookupTy("off64_t"); 2241 // void *mmap64(void *addr, size_t length, int prot, int flags, int fd, 2242 // off64_t offset); 2243 // FIXME: Improve for errno modeling. 2244 addToFunctionSummaryMap( 2245 "mmap64", 2246 Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy}, 2247 RetType{VoidPtrTy}), 2248 Summary(NoEvalCall) 2249 .ArgConstraint(ArgumentCondition(1, WithinRange, Range(1, SizeMax))) 2250 .ArgConstraint( 2251 ArgumentCondition(4, WithinRange, Range(-1, IntMax)))); 2252 2253 // int pipe(int fildes[2]); 2254 addToFunctionSummaryMap("pipe", 2255 Signature(ArgTypes{IntPtrTy}, RetType{IntTy}), 2256 Summary(NoEvalCall) 2257 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2258 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2259 .ArgConstraint(NotNull(ArgNo(0)))); 2260 2261 // off_t lseek(int fildes, off_t offset, int whence); 2262 // In the first case we can not tell for sure if it failed or not. 2263 // A return value different from of the expected offset (that is unknown 2264 // here) may indicate failure. For this reason we do not enforce the errno 2265 // check (can cause false positive). 2266 addToFunctionSummaryMap( 2267 "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}), 2268 Summary(NoEvalCall) 2269 .Case(ReturnsNonnegative, ErrnoIrrelevant) 2270 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2271 .ArgConstraint( 2272 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2273 2274 // ssize_t readlink(const char *restrict path, char *restrict buf, 2275 // size_t bufsize); 2276 addToFunctionSummaryMap( 2277 "readlink", 2278 Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, 2279 RetType{Ssize_tTy}), 2280 Summary(NoEvalCall) 2281 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2282 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2283 ErrnoMustNotBeChecked) 2284 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2285 .ArgConstraint(NotNull(ArgNo(0))) 2286 .ArgConstraint(NotNull(ArgNo(1))) 2287 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2288 /*BufSize=*/ArgNo(2))) 2289 .ArgConstraint( 2290 ArgumentCondition(2, WithinRange, Range(0, SizeMax)))); 2291 2292 // ssize_t readlinkat(int fd, const char *restrict path, 2293 // char *restrict buf, size_t bufsize); 2294 addToFunctionSummaryMap( 2295 "readlinkat", 2296 Signature( 2297 ArgTypes{IntTy, ConstCharPtrRestrictTy, CharPtrRestrictTy, SizeTy}, 2298 RetType{Ssize_tTy}), 2299 Summary(NoEvalCall) 2300 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)), 2301 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2302 ErrnoMustNotBeChecked) 2303 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2304 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2305 .ArgConstraint(NotNull(ArgNo(1))) 2306 .ArgConstraint(NotNull(ArgNo(2))) 2307 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(2), 2308 /*BufSize=*/ArgNo(3))) 2309 .ArgConstraint( 2310 ArgumentCondition(3, WithinRange, Range(0, SizeMax)))); 2311 2312 // int renameat(int olddirfd, const char *oldpath, int newdirfd, const char 2313 // *newpath); 2314 addToFunctionSummaryMap( 2315 "renameat", 2316 Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy}, 2317 RetType{IntTy}), 2318 Summary(NoEvalCall) 2319 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2320 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2321 .ArgConstraint(NotNull(ArgNo(1))) 2322 .ArgConstraint(NotNull(ArgNo(3)))); 2323 2324 // char *realpath(const char *restrict file_name, 2325 // char *restrict resolved_name); 2326 // FIXME: Improve for errno modeling. 2327 addToFunctionSummaryMap( 2328 "realpath", 2329 Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy}, 2330 RetType{CharPtrTy}), 2331 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2332 2333 QualType CharPtrConstPtr = getPointerTy(getConstTy(CharPtrTy)); 2334 2335 // int execv(const char *path, char *const argv[]); 2336 addToFunctionSummaryMap( 2337 "execv", 2338 Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}), 2339 Summary(NoEvalCall) 2340 .Case({ReturnValueCondition(WithinRange, SingleValue(-1))}, 2341 ErrnoIrrelevant) 2342 .ArgConstraint(NotNull(ArgNo(0)))); 2343 2344 // int execvp(const char *file, char *const argv[]); 2345 addToFunctionSummaryMap( 2346 "execvp", 2347 Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}), 2348 Summary(NoEvalCall) 2349 .Case({ReturnValueCondition(WithinRange, SingleValue(-1))}, 2350 ErrnoIrrelevant) 2351 .ArgConstraint(NotNull(ArgNo(0)))); 2352 2353 // int getopt(int argc, char * const argv[], const char *optstring); 2354 addToFunctionSummaryMap( 2355 "getopt", 2356 Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy}, 2357 RetType{IntTy}), 2358 Summary(NoEvalCall) 2359 .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))}, 2360 ErrnoIrrelevant) 2361 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2362 .ArgConstraint(NotNull(ArgNo(1))) 2363 .ArgConstraint(NotNull(ArgNo(2)))); 2364 2365 Optional<QualType> StructSockaddrTy = lookupTy("sockaddr"); 2366 Optional<QualType> StructSockaddrPtrTy = getPointerTy(StructSockaddrTy); 2367 Optional<QualType> ConstStructSockaddrPtrTy = 2368 getPointerTy(getConstTy(StructSockaddrTy)); 2369 Optional<QualType> StructSockaddrPtrRestrictTy = 2370 getRestrictTy(StructSockaddrPtrTy); 2371 Optional<QualType> ConstStructSockaddrPtrRestrictTy = 2372 getRestrictTy(ConstStructSockaddrPtrTy); 2373 Optional<QualType> Socklen_tTy = lookupTy("socklen_t"); 2374 Optional<QualType> Socklen_tPtrTy = getPointerTy(Socklen_tTy); 2375 Optional<QualType> Socklen_tPtrRestrictTy = getRestrictTy(Socklen_tPtrTy); 2376 Optional<RangeInt> Socklen_tMax = getMaxValue(Socklen_tTy); 2377 2378 // In 'socket.h' of some libc implementations with C99, sockaddr parameter 2379 // is a transparent union of the underlying sockaddr_ family of pointers 2380 // instead of being a pointer to struct sockaddr. In these cases, the 2381 // standardized signature will not match, thus we try to match with another 2382 // signature that has the joker Irrelevant type. We also remove those 2383 // constraints which require pointer types for the sockaddr param. 2384 auto Accept = 2385 Summary(NoEvalCall) 2386 .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked) 2387 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2388 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))); 2389 if (!addToFunctionSummaryMap( 2390 "accept", 2391 // int accept(int socket, struct sockaddr *restrict address, 2392 // socklen_t *restrict address_len); 2393 Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2394 Socklen_tPtrRestrictTy}, 2395 RetType{IntTy}), 2396 Accept)) 2397 addToFunctionSummaryMap( 2398 "accept", 2399 Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 2400 RetType{IntTy}), 2401 Accept); 2402 2403 // int bind(int socket, const struct sockaddr *address, socklen_t 2404 // address_len); 2405 if (!addToFunctionSummaryMap( 2406 "bind", 2407 Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, 2408 RetType{IntTy}), 2409 Summary(NoEvalCall) 2410 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2411 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2412 .ArgConstraint( 2413 ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2414 .ArgConstraint(NotNull(ArgNo(1))) 2415 .ArgConstraint( 2416 BufferSize(/*Buffer=*/ArgNo(1), /*BufSize=*/ArgNo(2))) 2417 .ArgConstraint( 2418 ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax))))) 2419 // Do not add constraints on sockaddr. 2420 addToFunctionSummaryMap( 2421 "bind", 2422 Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), 2423 Summary(NoEvalCall) 2424 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2425 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2426 .ArgConstraint( 2427 ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2428 .ArgConstraint( 2429 ArgumentCondition(2, WithinRange, Range(0, Socklen_tMax)))); 2430 2431 // int getpeername(int socket, struct sockaddr *restrict address, 2432 // socklen_t *restrict address_len); 2433 if (!addToFunctionSummaryMap( 2434 "getpeername", 2435 Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2436 Socklen_tPtrRestrictTy}, 2437 RetType{IntTy}), 2438 Summary(NoEvalCall) 2439 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2440 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2441 .ArgConstraint( 2442 ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2443 .ArgConstraint(NotNull(ArgNo(1))) 2444 .ArgConstraint(NotNull(ArgNo(2))))) 2445 addToFunctionSummaryMap( 2446 "getpeername", 2447 Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 2448 RetType{IntTy}), 2449 Summary(NoEvalCall) 2450 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2451 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2452 .ArgConstraint( 2453 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2454 2455 // int getsockname(int socket, struct sockaddr *restrict address, 2456 // socklen_t *restrict address_len); 2457 if (!addToFunctionSummaryMap( 2458 "getsockname", 2459 Signature(ArgTypes{IntTy, StructSockaddrPtrRestrictTy, 2460 Socklen_tPtrRestrictTy}, 2461 RetType{IntTy}), 2462 Summary(NoEvalCall) 2463 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2464 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2465 .ArgConstraint( 2466 ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2467 .ArgConstraint(NotNull(ArgNo(1))) 2468 .ArgConstraint(NotNull(ArgNo(2))))) 2469 addToFunctionSummaryMap( 2470 "getsockname", 2471 Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy}, 2472 RetType{IntTy}), 2473 Summary(NoEvalCall) 2474 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2475 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2476 .ArgConstraint( 2477 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2478 2479 // int connect(int socket, const struct sockaddr *address, socklen_t 2480 // address_len); 2481 if (!addToFunctionSummaryMap( 2482 "connect", 2483 Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy}, 2484 RetType{IntTy}), 2485 Summary(NoEvalCall) 2486 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2487 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2488 .ArgConstraint( 2489 ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2490 .ArgConstraint(NotNull(ArgNo(1))))) 2491 addToFunctionSummaryMap( 2492 "connect", 2493 Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}), 2494 Summary(NoEvalCall) 2495 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2496 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2497 .ArgConstraint( 2498 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2499 2500 auto Recvfrom = 2501 Summary(NoEvalCall) 2502 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2503 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2504 ErrnoMustNotBeChecked) 2505 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2506 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2507 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2508 /*BufSize=*/ArgNo(2))); 2509 if (!addToFunctionSummaryMap( 2510 "recvfrom", 2511 // ssize_t recvfrom(int socket, void *restrict buffer, 2512 // size_t length, 2513 // int flags, struct sockaddr *restrict address, 2514 // socklen_t *restrict address_len); 2515 Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, 2516 StructSockaddrPtrRestrictTy, 2517 Socklen_tPtrRestrictTy}, 2518 RetType{Ssize_tTy}), 2519 Recvfrom)) 2520 addToFunctionSummaryMap( 2521 "recvfrom", 2522 Signature(ArgTypes{IntTy, VoidPtrRestrictTy, SizeTy, IntTy, 2523 Irrelevant, Socklen_tPtrRestrictTy}, 2524 RetType{Ssize_tTy}), 2525 Recvfrom); 2526 2527 auto Sendto = 2528 Summary(NoEvalCall) 2529 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2530 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2531 ErrnoMustNotBeChecked) 2532 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2533 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2534 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2535 /*BufSize=*/ArgNo(2))); 2536 if (!addToFunctionSummaryMap( 2537 "sendto", 2538 // ssize_t sendto(int socket, const void *message, size_t length, 2539 // int flags, const struct sockaddr *dest_addr, 2540 // socklen_t dest_len); 2541 Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, 2542 ConstStructSockaddrPtrTy, Socklen_tTy}, 2543 RetType{Ssize_tTy}), 2544 Sendto)) 2545 addToFunctionSummaryMap( 2546 "sendto", 2547 Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy, Irrelevant, 2548 Socklen_tTy}, 2549 RetType{Ssize_tTy}), 2550 Sendto); 2551 2552 // int listen(int sockfd, int backlog); 2553 addToFunctionSummaryMap("listen", 2554 Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), 2555 Summary(NoEvalCall) 2556 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2557 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2558 .ArgConstraint(ArgumentCondition( 2559 0, WithinRange, Range(0, IntMax)))); 2560 2561 // ssize_t recv(int sockfd, void *buf, size_t len, int flags); 2562 addToFunctionSummaryMap( 2563 "recv", 2564 Signature(ArgTypes{IntTy, VoidPtrTy, SizeTy, IntTy}, 2565 RetType{Ssize_tTy}), 2566 Summary(NoEvalCall) 2567 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2568 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2569 ErrnoMustNotBeChecked) 2570 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2571 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2572 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2573 /*BufSize=*/ArgNo(2)))); 2574 2575 Optional<QualType> StructMsghdrTy = lookupTy("msghdr"); 2576 Optional<QualType> StructMsghdrPtrTy = getPointerTy(StructMsghdrTy); 2577 Optional<QualType> ConstStructMsghdrPtrTy = 2578 getPointerTy(getConstTy(StructMsghdrTy)); 2579 2580 // ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); 2581 addToFunctionSummaryMap( 2582 "recvmsg", 2583 Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy}, 2584 RetType{Ssize_tTy}), 2585 Summary(NoEvalCall) 2586 .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2587 ErrnoMustNotBeChecked) 2588 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2589 .ArgConstraint( 2590 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2591 2592 // ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags); 2593 addToFunctionSummaryMap( 2594 "sendmsg", 2595 Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy}, 2596 RetType{Ssize_tTy}), 2597 Summary(NoEvalCall) 2598 .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2599 ErrnoMustNotBeChecked) 2600 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2601 .ArgConstraint( 2602 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2603 2604 // int setsockopt(int socket, int level, int option_name, 2605 // const void *option_value, socklen_t option_len); 2606 addToFunctionSummaryMap( 2607 "setsockopt", 2608 Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy}, 2609 RetType{IntTy}), 2610 Summary(NoEvalCall) 2611 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2612 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2613 .ArgConstraint(NotNull(ArgNo(3))) 2614 .ArgConstraint( 2615 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4))) 2616 .ArgConstraint( 2617 ArgumentCondition(4, WithinRange, Range(0, Socklen_tMax)))); 2618 2619 // int getsockopt(int socket, int level, int option_name, 2620 // void *restrict option_value, 2621 // socklen_t *restrict option_len); 2622 addToFunctionSummaryMap( 2623 "getsockopt", 2624 Signature(ArgTypes{IntTy, IntTy, IntTy, VoidPtrRestrictTy, 2625 Socklen_tPtrRestrictTy}, 2626 RetType{IntTy}), 2627 Summary(NoEvalCall) 2628 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2629 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2630 .ArgConstraint(NotNull(ArgNo(3))) 2631 .ArgConstraint(NotNull(ArgNo(4)))); 2632 2633 // ssize_t send(int sockfd, const void *buf, size_t len, int flags); 2634 addToFunctionSummaryMap( 2635 "send", 2636 Signature(ArgTypes{IntTy, ConstVoidPtrTy, SizeTy, IntTy}, 2637 RetType{Ssize_tTy}), 2638 Summary(NoEvalCall) 2639 .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)), 2640 ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))}, 2641 ErrnoMustNotBeChecked) 2642 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2643 .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax))) 2644 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2645 /*BufSize=*/ArgNo(2)))); 2646 2647 // int socketpair(int domain, int type, int protocol, int sv[2]); 2648 addToFunctionSummaryMap( 2649 "socketpair", 2650 Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}), 2651 Summary(NoEvalCall) 2652 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2653 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2654 .ArgConstraint(NotNull(ArgNo(3)))); 2655 2656 // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen, 2657 // char *restrict node, socklen_t nodelen, 2658 // char *restrict service, 2659 // socklen_t servicelen, int flags); 2660 // 2661 // This is defined in netdb.h. And contrary to 'socket.h', the sockaddr 2662 // parameter is never handled as a transparent union in netdb.h 2663 addToFunctionSummaryMap( 2664 "getnameinfo", 2665 Signature(ArgTypes{ConstStructSockaddrPtrRestrictTy, Socklen_tTy, 2666 CharPtrRestrictTy, Socklen_tTy, CharPtrRestrictTy, 2667 Socklen_tTy, IntTy}, 2668 RetType{IntTy}), 2669 Summary(NoEvalCall) 2670 .ArgConstraint( 2671 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1))) 2672 .ArgConstraint( 2673 ArgumentCondition(1, WithinRange, Range(0, Socklen_tMax))) 2674 .ArgConstraint( 2675 BufferSize(/*Buffer=*/ArgNo(2), /*BufSize=*/ArgNo(3))) 2676 .ArgConstraint( 2677 ArgumentCondition(3, WithinRange, Range(0, Socklen_tMax))) 2678 .ArgConstraint( 2679 BufferSize(/*Buffer=*/ArgNo(4), /*BufSize=*/ArgNo(5))) 2680 .ArgConstraint( 2681 ArgumentCondition(5, WithinRange, Range(0, Socklen_tMax)))); 2682 2683 Optional<QualType> StructUtimbufTy = lookupTy("utimbuf"); 2684 Optional<QualType> StructUtimbufPtrTy = getPointerTy(StructUtimbufTy); 2685 2686 // int utime(const char *filename, struct utimbuf *buf); 2687 addToFunctionSummaryMap( 2688 "utime", 2689 Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}), 2690 Summary(NoEvalCall) 2691 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2692 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2693 .ArgConstraint(NotNull(ArgNo(0)))); 2694 2695 Optional<QualType> StructTimespecTy = lookupTy("timespec"); 2696 Optional<QualType> StructTimespecPtrTy = getPointerTy(StructTimespecTy); 2697 Optional<QualType> ConstStructTimespecPtrTy = 2698 getPointerTy(getConstTy(StructTimespecTy)); 2699 2700 // int futimens(int fd, const struct timespec times[2]); 2701 addToFunctionSummaryMap( 2702 "futimens", 2703 Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}), 2704 Summary(NoEvalCall) 2705 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2706 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2707 .ArgConstraint( 2708 ArgumentCondition(0, WithinRange, Range(0, IntMax)))); 2709 2710 // int utimensat(int dirfd, const char *pathname, 2711 // const struct timespec times[2], int flags); 2712 addToFunctionSummaryMap("utimensat", 2713 Signature(ArgTypes{IntTy, ConstCharPtrTy, 2714 ConstStructTimespecPtrTy, IntTy}, 2715 RetType{IntTy}), 2716 Summary(NoEvalCall) 2717 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2718 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2719 .ArgConstraint(NotNull(ArgNo(1)))); 2720 2721 Optional<QualType> StructTimevalTy = lookupTy("timeval"); 2722 Optional<QualType> ConstStructTimevalPtrTy = 2723 getPointerTy(getConstTy(StructTimevalTy)); 2724 2725 // int utimes(const char *filename, const struct timeval times[2]); 2726 addToFunctionSummaryMap( 2727 "utimes", 2728 Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy}, 2729 RetType{IntTy}), 2730 Summary(NoEvalCall) 2731 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2732 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2733 .ArgConstraint(NotNull(ArgNo(0)))); 2734 2735 // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); 2736 addToFunctionSummaryMap( 2737 "nanosleep", 2738 Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy}, 2739 RetType{IntTy}), 2740 Summary(NoEvalCall) 2741 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2742 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2743 .ArgConstraint(NotNull(ArgNo(0)))); 2744 2745 Optional<QualType> Time_tTy = lookupTy("time_t"); 2746 Optional<QualType> ConstTime_tPtrTy = getPointerTy(getConstTy(Time_tTy)); 2747 Optional<QualType> ConstTime_tPtrRestrictTy = 2748 getRestrictTy(ConstTime_tPtrTy); 2749 2750 Optional<QualType> StructTmTy = lookupTy("tm"); 2751 Optional<QualType> StructTmPtrTy = getPointerTy(StructTmTy); 2752 Optional<QualType> StructTmPtrRestrictTy = getRestrictTy(StructTmPtrTy); 2753 Optional<QualType> ConstStructTmPtrTy = 2754 getPointerTy(getConstTy(StructTmTy)); 2755 Optional<QualType> ConstStructTmPtrRestrictTy = 2756 getRestrictTy(ConstStructTmPtrTy); 2757 2758 // struct tm * localtime(const time_t *tp); 2759 addToFunctionSummaryMap( 2760 "localtime", 2761 Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}), 2762 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2763 2764 // struct tm *localtime_r(const time_t *restrict timer, 2765 // struct tm *restrict result); 2766 addToFunctionSummaryMap( 2767 "localtime_r", 2768 Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy}, 2769 RetType{StructTmPtrTy}), 2770 Summary(NoEvalCall) 2771 .ArgConstraint(NotNull(ArgNo(0))) 2772 .ArgConstraint(NotNull(ArgNo(1)))); 2773 2774 // char *asctime_r(const struct tm *restrict tm, char *restrict buf); 2775 addToFunctionSummaryMap( 2776 "asctime_r", 2777 Signature(ArgTypes{ConstStructTmPtrRestrictTy, CharPtrRestrictTy}, 2778 RetType{CharPtrTy}), 2779 Summary(NoEvalCall) 2780 .ArgConstraint(NotNull(ArgNo(0))) 2781 .ArgConstraint(NotNull(ArgNo(1))) 2782 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1), 2783 /*MinBufSize=*/BVF.getValue(26, IntTy)))); 2784 2785 // char *ctime_r(const time_t *timep, char *buf); 2786 addToFunctionSummaryMap( 2787 "ctime_r", 2788 Signature(ArgTypes{ConstTime_tPtrTy, CharPtrTy}, RetType{CharPtrTy}), 2789 Summary(NoEvalCall) 2790 .ArgConstraint(NotNull(ArgNo(0))) 2791 .ArgConstraint(NotNull(ArgNo(1))) 2792 .ArgConstraint(BufferSize( 2793 /*Buffer=*/ArgNo(1), 2794 /*MinBufSize=*/BVF.getValue(26, IntTy)))); 2795 2796 // struct tm *gmtime_r(const time_t *restrict timer, 2797 // struct tm *restrict result); 2798 addToFunctionSummaryMap( 2799 "gmtime_r", 2800 Signature(ArgTypes{ConstTime_tPtrRestrictTy, StructTmPtrRestrictTy}, 2801 RetType{StructTmPtrTy}), 2802 Summary(NoEvalCall) 2803 .ArgConstraint(NotNull(ArgNo(0))) 2804 .ArgConstraint(NotNull(ArgNo(1)))); 2805 2806 // struct tm * gmtime(const time_t *tp); 2807 addToFunctionSummaryMap( 2808 "gmtime", Signature(ArgTypes{ConstTime_tPtrTy}, RetType{StructTmPtrTy}), 2809 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2810 2811 Optional<QualType> Clockid_tTy = lookupTy("clockid_t"); 2812 2813 // int clock_gettime(clockid_t clock_id, struct timespec *tp); 2814 addToFunctionSummaryMap( 2815 "clock_gettime", 2816 Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}), 2817 Summary(NoEvalCall) 2818 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2819 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2820 .ArgConstraint(NotNull(ArgNo(1)))); 2821 2822 Optional<QualType> StructItimervalTy = lookupTy("itimerval"); 2823 Optional<QualType> StructItimervalPtrTy = getPointerTy(StructItimervalTy); 2824 2825 // int getitimer(int which, struct itimerval *curr_value); 2826 addToFunctionSummaryMap( 2827 "getitimer", 2828 Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}), 2829 Summary(NoEvalCall) 2830 .Case(ReturnsZero, ErrnoMustNotBeChecked) 2831 .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant) 2832 .ArgConstraint(NotNull(ArgNo(1)))); 2833 2834 Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t"); 2835 Optional<QualType> Pthread_cond_tPtrTy = getPointerTy(Pthread_cond_tTy); 2836 Optional<QualType> Pthread_tTy = lookupTy("pthread_t"); 2837 Optional<QualType> Pthread_tPtrTy = getPointerTy(Pthread_tTy); 2838 Optional<QualType> Pthread_tPtrRestrictTy = getRestrictTy(Pthread_tPtrTy); 2839 Optional<QualType> Pthread_mutex_tTy = lookupTy("pthread_mutex_t"); 2840 Optional<QualType> Pthread_mutex_tPtrTy = getPointerTy(Pthread_mutex_tTy); 2841 Optional<QualType> Pthread_mutex_tPtrRestrictTy = 2842 getRestrictTy(Pthread_mutex_tPtrTy); 2843 Optional<QualType> Pthread_attr_tTy = lookupTy("pthread_attr_t"); 2844 Optional<QualType> Pthread_attr_tPtrTy = getPointerTy(Pthread_attr_tTy); 2845 Optional<QualType> ConstPthread_attr_tPtrTy = 2846 getPointerTy(getConstTy(Pthread_attr_tTy)); 2847 Optional<QualType> ConstPthread_attr_tPtrRestrictTy = 2848 getRestrictTy(ConstPthread_attr_tPtrTy); 2849 Optional<QualType> Pthread_mutexattr_tTy = lookupTy("pthread_mutexattr_t"); 2850 Optional<QualType> ConstPthread_mutexattr_tPtrTy = 2851 getPointerTy(getConstTy(Pthread_mutexattr_tTy)); 2852 Optional<QualType> ConstPthread_mutexattr_tPtrRestrictTy = 2853 getRestrictTy(ConstPthread_mutexattr_tPtrTy); 2854 2855 QualType PthreadStartRoutineTy = getPointerTy( 2856 ACtx.getFunctionType(/*ResultTy=*/VoidPtrTy, /*Args=*/VoidPtrTy, 2857 FunctionProtoType::ExtProtoInfo())); 2858 2859 // int pthread_cond_signal(pthread_cond_t *cond); 2860 // int pthread_cond_broadcast(pthread_cond_t *cond); 2861 addToFunctionSummaryMap( 2862 {"pthread_cond_signal", "pthread_cond_broadcast"}, 2863 Signature(ArgTypes{Pthread_cond_tPtrTy}, RetType{IntTy}), 2864 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2865 2866 // int pthread_create(pthread_t *restrict thread, 2867 // const pthread_attr_t *restrict attr, 2868 // void *(*start_routine)(void*), void *restrict arg); 2869 addToFunctionSummaryMap( 2870 "pthread_create", 2871 Signature(ArgTypes{Pthread_tPtrRestrictTy, 2872 ConstPthread_attr_tPtrRestrictTy, 2873 PthreadStartRoutineTy, VoidPtrRestrictTy}, 2874 RetType{IntTy}), 2875 Summary(NoEvalCall) 2876 .ArgConstraint(NotNull(ArgNo(0))) 2877 .ArgConstraint(NotNull(ArgNo(2)))); 2878 2879 // int pthread_attr_destroy(pthread_attr_t *attr); 2880 // int pthread_attr_init(pthread_attr_t *attr); 2881 addToFunctionSummaryMap( 2882 {"pthread_attr_destroy", "pthread_attr_init"}, 2883 Signature(ArgTypes{Pthread_attr_tPtrTy}, RetType{IntTy}), 2884 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2885 2886 // int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, 2887 // size_t *restrict stacksize); 2888 // int pthread_attr_getguardsize(const pthread_attr_t *restrict attr, 2889 // size_t *restrict guardsize); 2890 addToFunctionSummaryMap( 2891 {"pthread_attr_getstacksize", "pthread_attr_getguardsize"}, 2892 Signature(ArgTypes{ConstPthread_attr_tPtrRestrictTy, SizePtrRestrictTy}, 2893 RetType{IntTy}), 2894 Summary(NoEvalCall) 2895 .ArgConstraint(NotNull(ArgNo(0))) 2896 .ArgConstraint(NotNull(ArgNo(1)))); 2897 2898 // int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); 2899 // int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize); 2900 addToFunctionSummaryMap( 2901 {"pthread_attr_setstacksize", "pthread_attr_setguardsize"}, 2902 Signature(ArgTypes{Pthread_attr_tPtrTy, SizeTy}, RetType{IntTy}), 2903 Summary(NoEvalCall) 2904 .ArgConstraint(NotNull(ArgNo(0))) 2905 .ArgConstraint( 2906 ArgumentCondition(1, WithinRange, Range(0, SizeMax)))); 2907 2908 // int pthread_mutex_init(pthread_mutex_t *restrict mutex, const 2909 // pthread_mutexattr_t *restrict attr); 2910 addToFunctionSummaryMap( 2911 "pthread_mutex_init", 2912 Signature(ArgTypes{Pthread_mutex_tPtrRestrictTy, 2913 ConstPthread_mutexattr_tPtrRestrictTy}, 2914 RetType{IntTy}), 2915 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2916 2917 // int pthread_mutex_destroy(pthread_mutex_t *mutex); 2918 // int pthread_mutex_lock(pthread_mutex_t *mutex); 2919 // int pthread_mutex_trylock(pthread_mutex_t *mutex); 2920 // int pthread_mutex_unlock(pthread_mutex_t *mutex); 2921 addToFunctionSummaryMap( 2922 {"pthread_mutex_destroy", "pthread_mutex_lock", "pthread_mutex_trylock", 2923 "pthread_mutex_unlock"}, 2924 Signature(ArgTypes{Pthread_mutex_tPtrTy}, RetType{IntTy}), 2925 Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0)))); 2926 } 2927 2928 // Functions for testing. 2929 if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) { 2930 addToFunctionSummaryMap( 2931 "__not_null", Signature(ArgTypes{IntPtrTy}, RetType{IntTy}), 2932 Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0)))); 2933 2934 // Test range values. 2935 addToFunctionSummaryMap( 2936 "__single_val_1", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2937 Summary(EvalCallAsPure) 2938 .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))); 2939 addToFunctionSummaryMap( 2940 "__range_1_2", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2941 Summary(EvalCallAsPure) 2942 .ArgConstraint(ArgumentCondition(0U, WithinRange, Range(1, 2)))); 2943 addToFunctionSummaryMap("__range_1_2__4_5", 2944 Signature(ArgTypes{IntTy}, RetType{IntTy}), 2945 Summary(EvalCallAsPure) 2946 .ArgConstraint(ArgumentCondition( 2947 0U, WithinRange, Range({1, 2}, {4, 5})))); 2948 2949 // Test range kind. 2950 addToFunctionSummaryMap( 2951 "__within", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2952 Summary(EvalCallAsPure) 2953 .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1)))); 2954 addToFunctionSummaryMap( 2955 "__out_of", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2956 Summary(EvalCallAsPure) 2957 .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1)))); 2958 2959 addToFunctionSummaryMap( 2960 "__two_constrained_args", 2961 Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}), 2962 Summary(EvalCallAsPure) 2963 .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))) 2964 .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1)))); 2965 addToFunctionSummaryMap( 2966 "__arg_constrained_twice", Signature(ArgTypes{IntTy}, RetType{IntTy}), 2967 Summary(EvalCallAsPure) 2968 .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))) 2969 .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2)))); 2970 addToFunctionSummaryMap( 2971 "__defaultparam", 2972 Signature(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}), 2973 Summary(EvalCallAsPure).ArgConstraint(NotNull(ArgNo(0)))); 2974 addToFunctionSummaryMap( 2975 "__variadic", 2976 Signature(ArgTypes{VoidPtrTy, ConstCharPtrTy}, RetType{IntTy}), 2977 Summary(EvalCallAsPure) 2978 .ArgConstraint(NotNull(ArgNo(0))) 2979 .ArgConstraint(NotNull(ArgNo(1)))); 2980 addToFunctionSummaryMap( 2981 "__buf_size_arg_constraint", 2982 Signature(ArgTypes{ConstVoidPtrTy, SizeTy}, RetType{IntTy}), 2983 Summary(EvalCallAsPure) 2984 .ArgConstraint( 2985 BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1)))); 2986 addToFunctionSummaryMap( 2987 "__buf_size_arg_constraint_mul", 2988 Signature(ArgTypes{ConstVoidPtrTy, SizeTy, SizeTy}, RetType{IntTy}), 2989 Summary(EvalCallAsPure) 2990 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1), 2991 /*BufSizeMultiplier=*/ArgNo(2)))); 2992 addToFunctionSummaryMap( 2993 "__buf_size_arg_constraint_concrete", 2994 Signature(ArgTypes{ConstVoidPtrTy}, RetType{IntTy}), 2995 Summary(EvalCallAsPure) 2996 .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), 2997 /*BufSize=*/BVF.getValue(10, IntTy)))); 2998 addToFunctionSummaryMap( 2999 {"__test_restrict_param_0", "__test_restrict_param_1", 3000 "__test_restrict_param_2"}, 3001 Signature(ArgTypes{VoidPtrRestrictTy}, RetType{VoidTy}), 3002 Summary(EvalCallAsPure)); 3003 } 3004 3005 SummariesInitialized = true; 3006 } 3007 3008 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) { 3009 auto *Checker = mgr.registerChecker<StdLibraryFunctionsChecker>(); 3010 const AnalyzerOptions &Opts = mgr.getAnalyzerOptions(); 3011 Checker->DisplayLoadedSummaries = 3012 Opts.getCheckerBooleanOption(Checker, "DisplayLoadedSummaries"); 3013 Checker->ModelPOSIX = Opts.getCheckerBooleanOption(Checker, "ModelPOSIX"); 3014 Checker->ShouldAssumeControlledEnvironment = 3015 Opts.ShouldAssumeControlledEnvironment; 3016 } 3017 3018 bool ento::shouldRegisterStdCLibraryFunctionsChecker( 3019 const CheckerManager &mgr) { 3020 return true; 3021 } 3022 3023 #define REGISTER_CHECKER(name) \ 3024 void ento::register##name(CheckerManager &mgr) { \ 3025 StdLibraryFunctionsChecker *checker = \ 3026 mgr.getChecker<StdLibraryFunctionsChecker>(); \ 3027 checker->ChecksEnabled[StdLibraryFunctionsChecker::CK_##name] = true; \ 3028 checker->CheckNames[StdLibraryFunctionsChecker::CK_##name] = \ 3029 mgr.getCurrentCheckerName(); \ 3030 } \ 3031 \ 3032 bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } 3033 3034 REGISTER_CHECKER(StdCLibraryFunctionArgsChecker) 3035 REGISTER_CHECKER(StdCLibraryFunctionsTesterChecker) 3036