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 // It does not generate warnings. 11 // 12 // This checker provides a specification format - `FunctionSummaryTy' - and 13 // contains descriptions of some library functions in this format. Each 14 // specification contains a list of branches for splitting the program state 15 // upon call, and range constraints on argument and return-value symbols that 16 // are satisfied on each branch. This spec can be expanded to include more 17 // items, like external effects of the function. 18 // 19 // The main difference between this approach and the body farms technique is 20 // in more explicit control over how many branches are produced. For example, 21 // consider standard C function `ispunct(int x)', which returns a non-zero value 22 // iff `x' is a punctuation character, that is, when `x' is in range 23 // ['!', '/'] [':', '@'] U ['[', '\`'] U ['{', '~']. 24 // `FunctionSummaryTy' provides only two branches for this function. However, 25 // any attempt to describe this range with if-statements in the body farm 26 // would result in many more branches. Because each branch needs to be analyzed 27 // independently, this significantly reduces performance. Additionally, 28 // once we consider a branch on which `x' is in range, say, ['!', '/'], 29 // we assume that such branch is an important separate path through the program, 30 // which may lead to false positives because considering this particular path 31 // was not consciously intended, and therefore it might have been unreachable. 32 // 33 // This checker uses eval::Call for modeling "pure" functions, for which 34 // their `FunctionSummaryTy' is a precise model. This avoids unnecessary 35 // invalidation passes. Conflicts with other checkers are unlikely because 36 // if the function has no other effects, other checkers would probably never 37 // want to improve upon the modeling done by this checker. 38 // 39 // Non-"pure" functions, for which only partial improvement over the default 40 // behavior is expected, are modeled via check::PostCall, non-intrusively. 41 // 42 // The following standard C functions are currently supported: 43 // 44 // fgetc getline isdigit isupper 45 // fread isalnum isgraph isxdigit 46 // fwrite isalpha islower read 47 // getc isascii isprint write 48 // getchar isblank ispunct 49 // getdelim iscntrl isspace 50 // 51 //===----------------------------------------------------------------------===// 52 53 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h" 54 #include "clang/StaticAnalyzer/Core/Checker.h" 55 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 56 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 57 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 58 59 using namespace clang; 60 using namespace clang::ento; 61 62 namespace { 63 class StdLibraryFunctionsChecker : public Checker<check::PostCall, eval::Call> { 64 /// Below is a series of typedefs necessary to define function specs. 65 /// We avoid nesting types here because each additional qualifier 66 /// would need to be repeated in every function spec. 67 struct FunctionSummaryTy; 68 69 /// Specify how much the analyzer engine should entrust modeling this function 70 /// to us. If he doesn't, he performs additional invalidations. 71 enum InvalidationKindTy { NoEvalCall, EvalCallAsPure }; 72 73 /// A pair of ValueRangeKindTy and IntRangeVectorTy would describe a range 74 /// imposed on a particular argument or return value symbol. 75 /// 76 /// Given a range, should the argument stay inside or outside this range? 77 /// The special `ComparesToArgument' value indicates that we should 78 /// impose a constraint that involves other argument or return value symbols. 79 enum ValueRangeKindTy { OutOfRange, WithinRange, ComparesToArgument }; 80 81 // The universal integral type to use in value range descriptions. 82 // Unsigned to make sure overflows are well-defined. 83 typedef uint64_t RangeIntTy; 84 85 /// Normally, describes a single range constraint, eg. {{0, 1}, {3, 4}} is 86 /// a non-negative integer, which less than 5 and not equal to 2. For 87 /// `ComparesToArgument', holds information about how exactly to compare to 88 /// the argument. 89 typedef std::vector<std::pair<RangeIntTy, RangeIntTy>> IntRangeVectorTy; 90 91 /// A reference to an argument or return value by its number. 92 /// ArgNo in CallExpr and CallEvent is defined as Unsigned, but 93 /// obviously uint32_t should be enough for all practical purposes. 94 typedef uint32_t ArgNoTy; 95 static const ArgNoTy Ret = std::numeric_limits<ArgNoTy>::max(); 96 97 /// Incapsulates a single range on a single symbol within a branch. 98 class ValueRange { 99 ArgNoTy ArgNo; // Argument to which we apply the range. 100 ValueRangeKindTy Kind; // Kind of range definition. 101 IntRangeVectorTy Args; // Polymorphic arguments. 102 103 public: 104 ValueRange(ArgNoTy ArgNo, ValueRangeKindTy Kind, 105 const IntRangeVectorTy &Args) 106 : ArgNo(ArgNo), Kind(Kind), Args(Args) {} 107 108 ArgNoTy getArgNo() const { return ArgNo; } 109 ValueRangeKindTy getKind() const { return Kind; } 110 111 BinaryOperator::Opcode getOpcode() const { 112 assert(Kind == ComparesToArgument); 113 assert(Args.size() == 1); 114 BinaryOperator::Opcode Op = 115 static_cast<BinaryOperator::Opcode>(Args[0].first); 116 assert(BinaryOperator::isComparisonOp(Op) && 117 "Only comparison ops are supported for ComparesToArgument"); 118 return Op; 119 } 120 121 ArgNoTy getOtherArgNo() const { 122 assert(Kind == ComparesToArgument); 123 assert(Args.size() == 1); 124 return static_cast<ArgNoTy>(Args[0].second); 125 } 126 127 const IntRangeVectorTy &getRanges() const { 128 assert(Kind != ComparesToArgument); 129 return Args; 130 } 131 132 // We avoid creating a virtual apply() method because 133 // it makes initializer lists harder to write. 134 private: 135 ProgramStateRef 136 applyAsOutOfRange(ProgramStateRef State, const CallEvent &Call, 137 const FunctionSummaryTy &Summary) const; 138 ProgramStateRef 139 applyAsWithinRange(ProgramStateRef State, const CallEvent &Call, 140 const FunctionSummaryTy &Summary) const; 141 ProgramStateRef 142 applyAsComparesToArgument(ProgramStateRef State, const CallEvent &Call, 143 const FunctionSummaryTy &Summary) const; 144 145 public: 146 ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call, 147 const FunctionSummaryTy &Summary) const { 148 switch (Kind) { 149 case OutOfRange: 150 return applyAsOutOfRange(State, Call, Summary); 151 case WithinRange: 152 return applyAsWithinRange(State, Call, Summary); 153 case ComparesToArgument: 154 return applyAsComparesToArgument(State, Call, Summary); 155 } 156 llvm_unreachable("Unknown ValueRange kind!"); 157 } 158 }; 159 160 /// The complete list of ranges that defines a single branch. 161 typedef std::vector<ValueRange> ValueRangeSet; 162 163 /// Includes information about function prototype (which is necessary to 164 /// ensure we're modeling the right function and casting values properly), 165 /// approach to invalidation, and a list of branches - essentially, a list 166 /// of list of ranges - essentially, a list of lists of lists of segments. 167 struct FunctionSummaryTy { 168 const std::vector<QualType> ArgTypes; 169 const QualType RetType; 170 const InvalidationKindTy InvalidationKind; 171 const std::vector<ValueRangeSet> Ranges; 172 173 private: 174 static void assertTypeSuitableForSummary(QualType T) { 175 assert(!T->isVoidType() && 176 "We should have had no significant void types in the spec"); 177 assert(T.isCanonical() && 178 "We should only have canonical types in the spec"); 179 // FIXME: lift this assert (but not the ones above!) 180 assert(T->isIntegralOrEnumerationType() && 181 "We only support integral ranges in the spec"); 182 } 183 184 public: 185 QualType getArgType(ArgNoTy ArgNo) const { 186 QualType T = (ArgNo == Ret) ? RetType : ArgTypes[ArgNo]; 187 assertTypeSuitableForSummary(T); 188 return T; 189 } 190 191 /// Try our best to figure out if the call expression is the call of 192 /// *the* library function to which this specification applies. 193 bool matchesCall(const CallExpr *CE) const; 194 }; 195 196 // The same function (as in, function identifier) may have different 197 // summaries assigned to it, with different argument and return value types. 198 // We call these "variants" of the function. This can be useful for handling 199 // C++ function overloads, and also it can be used when the same function 200 // may have different definitions on different platforms. 201 typedef std::vector<FunctionSummaryTy> FunctionVariantsTy; 202 203 // The map of all functions supported by the checker. It is initialized 204 // lazily, and it doesn't change after initialization. 205 typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy; 206 mutable FunctionSummaryMapTy FunctionSummaryMap; 207 208 // Auxiliary functions to support ArgNoTy within all structures 209 // in a unified manner. 210 static QualType getArgType(const FunctionSummaryTy &Summary, ArgNoTy ArgNo) { 211 return Summary.getArgType(ArgNo); 212 } 213 static QualType getArgType(const CallEvent &Call, ArgNoTy ArgNo) { 214 return ArgNo == Ret ? Call.getResultType().getCanonicalType() 215 : Call.getArgExpr(ArgNo)->getType().getCanonicalType(); 216 } 217 static QualType getArgType(const CallExpr *CE, ArgNoTy ArgNo) { 218 return ArgNo == Ret ? CE->getType().getCanonicalType() 219 : CE->getArg(ArgNo)->getType().getCanonicalType(); 220 } 221 static SVal getArgSVal(const CallEvent &Call, ArgNoTy ArgNo) { 222 return ArgNo == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgNo); 223 } 224 225 public: 226 void checkPostCall(const CallEvent &Call, CheckerContext &C) const; 227 bool evalCall(const CallEvent &Call, CheckerContext &C) const; 228 229 private: 230 Optional<FunctionSummaryTy> findFunctionSummary(const FunctionDecl *FD, 231 const CallExpr *CE, 232 CheckerContext &C) const; 233 234 void initFunctionSummaries(BasicValueFactory &BVF) const; 235 }; 236 } // end of anonymous namespace 237 238 ProgramStateRef StdLibraryFunctionsChecker::ValueRange::applyAsOutOfRange( 239 ProgramStateRef State, const CallEvent &Call, 240 const FunctionSummaryTy &Summary) const { 241 242 ProgramStateManager &Mgr = State->getStateManager(); 243 SValBuilder &SVB = Mgr.getSValBuilder(); 244 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 245 ConstraintManager &CM = Mgr.getConstraintManager(); 246 QualType T = getArgType(Summary, getArgNo()); 247 SVal V = getArgSVal(Call, getArgNo()); 248 249 if (auto N = V.getAs<NonLoc>()) { 250 const IntRangeVectorTy &R = getRanges(); 251 size_t E = R.size(); 252 for (size_t I = 0; I != E; ++I) { 253 const llvm::APSInt &Min = BVF.getValue(R[I].first, T); 254 const llvm::APSInt &Max = BVF.getValue(R[I].second, T); 255 assert(Min <= Max); 256 State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 257 if (!State) 258 break; 259 } 260 } 261 262 return State; 263 } 264 265 ProgramStateRef 266 StdLibraryFunctionsChecker::ValueRange::applyAsWithinRange( 267 ProgramStateRef State, const CallEvent &Call, 268 const FunctionSummaryTy &Summary) const { 269 270 ProgramStateManager &Mgr = State->getStateManager(); 271 SValBuilder &SVB = Mgr.getSValBuilder(); 272 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 273 ConstraintManager &CM = Mgr.getConstraintManager(); 274 QualType T = getArgType(Summary, getArgNo()); 275 SVal V = getArgSVal(Call, getArgNo()); 276 277 // "WithinRange R" is treated as "outside [T_MIN, T_MAX] \ R". 278 // We cut off [T_MIN, min(R) - 1] and [max(R) + 1, T_MAX] if necessary, 279 // and then cut away all holes in R one by one. 280 if (auto N = V.getAs<NonLoc>()) { 281 const IntRangeVectorTy &R = getRanges(); 282 size_t E = R.size(); 283 284 const llvm::APSInt &MinusInf = BVF.getMinValue(T); 285 const llvm::APSInt &PlusInf = BVF.getMaxValue(T); 286 287 const llvm::APSInt &Left = BVF.getValue(R[0].first - 1ULL, T); 288 if (Left != PlusInf) { 289 assert(MinusInf <= Left); 290 State = CM.assumeInclusiveRange(State, *N, MinusInf, Left, false); 291 if (!State) 292 return nullptr; 293 } 294 295 const llvm::APSInt &Right = BVF.getValue(R[E - 1].second + 1ULL, T); 296 if (Right != MinusInf) { 297 assert(Right <= PlusInf); 298 State = CM.assumeInclusiveRange(State, *N, Right, PlusInf, false); 299 if (!State) 300 return nullptr; 301 } 302 303 for (size_t I = 1; I != E; ++I) { 304 const llvm::APSInt &Min = BVF.getValue(R[I - 1].second + 1ULL, T); 305 const llvm::APSInt &Max = BVF.getValue(R[I].first - 1ULL, T); 306 assert(Min <= Max); 307 State = CM.assumeInclusiveRange(State, *N, Min, Max, false); 308 if (!State) 309 return nullptr; 310 } 311 } 312 313 return State; 314 } 315 316 ProgramStateRef 317 StdLibraryFunctionsChecker::ValueRange::applyAsComparesToArgument( 318 ProgramStateRef State, const CallEvent &Call, 319 const FunctionSummaryTy &Summary) const { 320 321 ProgramStateManager &Mgr = State->getStateManager(); 322 SValBuilder &SVB = Mgr.getSValBuilder(); 323 QualType CondT = SVB.getConditionType(); 324 QualType T = getArgType(Summary, getArgNo()); 325 SVal V = getArgSVal(Call, getArgNo()); 326 327 BinaryOperator::Opcode Op = getOpcode(); 328 ArgNoTy OtherArg = getOtherArgNo(); 329 SVal OtherV = getArgSVal(Call, OtherArg); 330 QualType OtherT = getArgType(Call, OtherArg); 331 // Note: we avoid integral promotion for comparison. 332 OtherV = SVB.evalCast(OtherV, T, OtherT); 333 if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT) 334 .getAs<DefinedOrUnknownSVal>()) 335 State = State->assume(*CompV, true); 336 return State; 337 } 338 339 void StdLibraryFunctionsChecker::checkPostCall(const CallEvent &Call, 340 CheckerContext &C) const { 341 const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); 342 if (!FD) 343 return; 344 345 const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); 346 if (!CE) 347 return; 348 349 Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C); 350 if (!FoundSummary) 351 return; 352 353 // Now apply ranges. 354 const FunctionSummaryTy &Summary = *FoundSummary; 355 ProgramStateRef State = C.getState(); 356 357 for (const auto &VRS: Summary.Ranges) { 358 ProgramStateRef NewState = State; 359 for (const auto &VR: VRS) { 360 NewState = VR.apply(NewState, Call, Summary); 361 if (!NewState) 362 break; 363 } 364 365 if (NewState && NewState != State) 366 C.addTransition(NewState); 367 } 368 } 369 370 bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call, 371 CheckerContext &C) const { 372 const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl()); 373 if (!FD) 374 return false; 375 376 const auto *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()); 377 if (!CE) 378 return false; 379 380 Optional<FunctionSummaryTy> FoundSummary = findFunctionSummary(FD, CE, C); 381 if (!FoundSummary) 382 return false; 383 384 const FunctionSummaryTy &Summary = *FoundSummary; 385 switch (Summary.InvalidationKind) { 386 case EvalCallAsPure: { 387 ProgramStateRef State = C.getState(); 388 const LocationContext *LC = C.getLocationContext(); 389 SVal V = C.getSValBuilder().conjureSymbolVal( 390 CE, LC, CE->getType().getCanonicalType(), C.blockCount()); 391 State = State->BindExpr(CE, LC, V); 392 C.addTransition(State); 393 return true; 394 } 395 case NoEvalCall: 396 // Summary tells us to avoid performing eval::Call. The function is possibly 397 // evaluated by another checker, or evaluated conservatively. 398 return false; 399 } 400 llvm_unreachable("Unknown invalidation kind!"); 401 } 402 403 bool StdLibraryFunctionsChecker::FunctionSummaryTy::matchesCall( 404 const CallExpr *CE) const { 405 // Check number of arguments: 406 if (CE->getNumArgs() != ArgTypes.size()) 407 return false; 408 409 // Check return type if relevant: 410 if (!RetType.isNull() && RetType != CE->getType().getCanonicalType()) 411 return false; 412 413 // Check argument types when relevant: 414 for (size_t I = 0, E = ArgTypes.size(); I != E; ++I) { 415 QualType FormalT = ArgTypes[I]; 416 // Null type marks irrelevant arguments. 417 if (FormalT.isNull()) 418 continue; 419 420 assertTypeSuitableForSummary(FormalT); 421 422 QualType ActualT = StdLibraryFunctionsChecker::getArgType(CE, I); 423 assert(ActualT.isCanonical()); 424 if (ActualT != FormalT) 425 return false; 426 } 427 428 return true; 429 } 430 431 Optional<StdLibraryFunctionsChecker::FunctionSummaryTy> 432 StdLibraryFunctionsChecker::findFunctionSummary(const FunctionDecl *FD, 433 const CallExpr *CE, 434 CheckerContext &C) const { 435 // Note: we cannot always obtain FD from CE 436 // (eg. virtual call, or call by pointer). 437 assert(CE); 438 439 if (!FD) 440 return None; 441 442 SValBuilder &SVB = C.getSValBuilder(); 443 BasicValueFactory &BVF = SVB.getBasicValueFactory(); 444 initFunctionSummaries(BVF); 445 446 IdentifierInfo *II = FD->getIdentifier(); 447 if (!II) 448 return None; 449 StringRef Name = II->getName(); 450 if (Name.empty() || !C.isCLibraryFunction(FD, Name)) 451 return None; 452 453 auto FSMI = FunctionSummaryMap.find(Name); 454 if (FSMI == FunctionSummaryMap.end()) 455 return None; 456 457 // Verify that function signature matches the spec in advance. 458 // Otherwise we might be modeling the wrong function. 459 // Strict checking is important because we will be conducting 460 // very integral-type-sensitive operations on arguments and 461 // return values. 462 const FunctionVariantsTy &SpecVariants = FSMI->second; 463 for (const FunctionSummaryTy &Spec : SpecVariants) 464 if (Spec.matchesCall(CE)) 465 return Spec; 466 467 return None; 468 } 469 470 void StdLibraryFunctionsChecker::initFunctionSummaries( 471 BasicValueFactory &BVF) const { 472 if (!FunctionSummaryMap.empty()) 473 return; 474 475 ASTContext &ACtx = BVF.getContext(); 476 477 // These types are useful for writing specifications quickly, 478 // New specifications should probably introduce more types. 479 // Some types are hard to obtain from the AST, eg. "ssize_t". 480 // In such cases it should be possible to provide multiple variants 481 // of function summary for common cases (eg. ssize_t could be int or long 482 // or long long, so three summary variants would be enough). 483 // Of course, function variants are also useful for C++ overloads. 484 QualType Irrelevant; // A placeholder, whenever we do not care about the type. 485 QualType IntTy = ACtx.IntTy; 486 QualType LongTy = ACtx.LongTy; 487 QualType LongLongTy = ACtx.LongLongTy; 488 QualType SizeTy = ACtx.getSizeType(); 489 490 RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue(); 491 RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue(); 492 RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue(); 493 494 // We are finally ready to define specifications for all supported functions. 495 // 496 // The signature needs to have the correct number of arguments. 497 // However, we insert `Irrelevant' when the type is insignificant. 498 // 499 // Argument ranges should always cover all variants. If return value 500 // is completely unknown, omit it from the respective range set. 501 // 502 // All types in the spec need to be canonical. 503 // 504 // Every item in the list of range sets represents a particular 505 // execution path the analyzer would need to explore once 506 // the call is modeled - a new program state is constructed 507 // for every range set, and each range line in the range set 508 // corresponds to a specific constraint within this state. 509 // 510 // Upon comparing to another argument, the other argument is casted 511 // to the current argument's type. This avoids proper promotion but 512 // seems useful. For example, read() receives size_t argument, 513 // and its return value, which is of type ssize_t, cannot be greater 514 // than this argument. If we made a promotion, and the size argument 515 // is equal to, say, 10, then we'd impose a range of [0, 10] on the 516 // return value, however the correct range is [-1, 10]. 517 // 518 // Please update the list of functions in the header after editing! 519 // 520 // The format is as follows: 521 // 522 //{ "function name", 523 // { spec: 524 // { argument types list, ... }, 525 // return type, purity, { range set list: 526 // { range list: 527 // { argument index, within or out of, {{from, to}, ...} }, 528 // { argument index, compares to argument, {{how, which}} }, 529 // ... 530 // } 531 // } 532 // } 533 //} 534 535 #define SUMMARY_WITH_VARIANTS(identifier) {#identifier, { 536 #define END_SUMMARY_WITH_VARIANTS }}, 537 #define VARIANT(argument_types, return_type, invalidation_approach) \ 538 { argument_types, return_type, invalidation_approach, { 539 #define END_VARIANT } }, 540 #define SUMMARY(identifier, argument_types, return_type, \ 541 invalidation_approach) \ 542 { #identifier, { { argument_types, return_type, invalidation_approach, { 543 #define END_SUMMARY } } } }, 544 #define ARGUMENT_TYPES(...) { __VA_ARGS__ } 545 #define RETURN_TYPE(x) x 546 #define INVALIDATION_APPROACH(x) x 547 #define CASE { 548 #define END_CASE }, 549 #define ARGUMENT_CONDITION(argument_number, condition_kind) \ 550 { argument_number, condition_kind, { 551 #define END_ARGUMENT_CONDITION }}, 552 #define RETURN_VALUE_CONDITION(condition_kind) \ 553 { Ret, condition_kind, { 554 #define END_RETURN_VALUE_CONDITION }}, 555 #define ARG_NO(x) x##U 556 #define RANGE(x, y) { x, y }, 557 #define SINGLE_VALUE(x) RANGE(x, x) 558 #define IS_LESS_THAN(arg) { BO_LE, arg } 559 560 FunctionSummaryMap = { 561 // The isascii() family of functions. 562 SUMMARY(isalnum, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 563 INVALIDATION_APPROACH(EvalCallAsPure)) 564 CASE // Boils down to isupper() or islower() or isdigit() 565 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 566 RANGE('0', '9') 567 RANGE('A', 'Z') 568 RANGE('a', 'z') 569 END_ARGUMENT_CONDITION 570 RETURN_VALUE_CONDITION(OutOfRange) 571 SINGLE_VALUE(0) 572 END_RETURN_VALUE_CONDITION 573 END_CASE 574 CASE // The locale-specific range. 575 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 576 RANGE(128, 255) 577 END_ARGUMENT_CONDITION 578 // No post-condition. We are completely unaware of 579 // locale-specific return values. 580 END_CASE 581 CASE 582 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 583 RANGE('0', '9') 584 RANGE('A', 'Z') 585 RANGE('a', 'z') 586 RANGE(128, 255) 587 END_ARGUMENT_CONDITION 588 RETURN_VALUE_CONDITION(WithinRange) 589 SINGLE_VALUE(0) 590 END_RETURN_VALUE_CONDITION 591 END_CASE 592 END_SUMMARY 593 SUMMARY(isalpha, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 594 INVALIDATION_APPROACH(EvalCallAsPure)) 595 CASE // isupper() or islower(). Note that 'Z' is less than 'a'. 596 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 597 RANGE('A', 'Z') 598 RANGE('a', 'z') 599 END_ARGUMENT_CONDITION 600 RETURN_VALUE_CONDITION(OutOfRange) 601 SINGLE_VALUE(0) 602 END_RETURN_VALUE_CONDITION 603 END_CASE 604 CASE // The locale-specific range. 605 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 606 RANGE(128, 255) 607 END_ARGUMENT_CONDITION 608 END_CASE 609 CASE // Other. 610 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 611 RANGE('A', 'Z') 612 RANGE('a', 'z') 613 RANGE(128, 255) 614 END_ARGUMENT_CONDITION 615 RETURN_VALUE_CONDITION(WithinRange) 616 SINGLE_VALUE(0) 617 END_RETURN_VALUE_CONDITION 618 END_CASE 619 END_SUMMARY 620 SUMMARY(isascii, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 621 INVALIDATION_APPROACH(EvalCallAsPure)) 622 CASE // Is ASCII. 623 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 624 RANGE(0, 127) 625 END_ARGUMENT_CONDITION 626 RETURN_VALUE_CONDITION(OutOfRange) 627 SINGLE_VALUE(0) 628 END_RETURN_VALUE_CONDITION 629 END_CASE 630 CASE 631 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 632 RANGE(0, 127) 633 END_ARGUMENT_CONDITION 634 RETURN_VALUE_CONDITION(WithinRange) 635 SINGLE_VALUE(0) 636 END_RETURN_VALUE_CONDITION 637 END_CASE 638 END_SUMMARY 639 SUMMARY(isblank, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 640 INVALIDATION_APPROACH(EvalCallAsPure)) 641 CASE 642 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 643 SINGLE_VALUE('\t') 644 SINGLE_VALUE(' ') 645 END_ARGUMENT_CONDITION 646 RETURN_VALUE_CONDITION(OutOfRange) 647 SINGLE_VALUE(0) 648 END_RETURN_VALUE_CONDITION 649 END_CASE 650 CASE 651 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 652 SINGLE_VALUE('\t') 653 SINGLE_VALUE(' ') 654 END_ARGUMENT_CONDITION 655 RETURN_VALUE_CONDITION(WithinRange) 656 SINGLE_VALUE(0) 657 END_RETURN_VALUE_CONDITION 658 END_CASE 659 END_SUMMARY 660 SUMMARY(iscntrl, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 661 INVALIDATION_APPROACH(EvalCallAsPure)) 662 CASE // 0..31 or 127 663 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 664 RANGE(0, 32) 665 SINGLE_VALUE(127) 666 END_ARGUMENT_CONDITION 667 RETURN_VALUE_CONDITION(OutOfRange) 668 SINGLE_VALUE(0) 669 END_RETURN_VALUE_CONDITION 670 END_CASE 671 CASE 672 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 673 RANGE(0, 32) 674 SINGLE_VALUE(127) 675 END_ARGUMENT_CONDITION 676 RETURN_VALUE_CONDITION(WithinRange) 677 SINGLE_VALUE(0) 678 END_RETURN_VALUE_CONDITION 679 END_CASE 680 END_SUMMARY 681 SUMMARY(isdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 682 INVALIDATION_APPROACH(EvalCallAsPure)) 683 CASE // Is a digit. 684 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 685 RANGE('0', '9') 686 END_ARGUMENT_CONDITION 687 RETURN_VALUE_CONDITION(OutOfRange) 688 SINGLE_VALUE(0) 689 END_RETURN_VALUE_CONDITION 690 END_CASE 691 CASE 692 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 693 RANGE('0', '9') 694 END_ARGUMENT_CONDITION 695 RETURN_VALUE_CONDITION(WithinRange) 696 SINGLE_VALUE(0) 697 END_RETURN_VALUE_CONDITION 698 END_CASE 699 END_SUMMARY 700 SUMMARY(isgraph, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 701 INVALIDATION_APPROACH(EvalCallAsPure)) 702 CASE 703 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 704 RANGE(33, 126) 705 END_ARGUMENT_CONDITION 706 RETURN_VALUE_CONDITION(OutOfRange) 707 SINGLE_VALUE(0) 708 END_RETURN_VALUE_CONDITION 709 END_CASE 710 CASE 711 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 712 RANGE(33, 126) 713 END_ARGUMENT_CONDITION 714 RETURN_VALUE_CONDITION(WithinRange) 715 SINGLE_VALUE(0) 716 END_RETURN_VALUE_CONDITION 717 END_CASE 718 END_SUMMARY 719 SUMMARY(islower, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 720 INVALIDATION_APPROACH(EvalCallAsPure)) 721 CASE // Is certainly lowercase. 722 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 723 RANGE('a', 'z') 724 END_ARGUMENT_CONDITION 725 RETURN_VALUE_CONDITION(OutOfRange) 726 SINGLE_VALUE(0) 727 END_RETURN_VALUE_CONDITION 728 END_CASE 729 CASE // Is ascii but not lowercase. 730 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 731 RANGE(0, 127) 732 END_ARGUMENT_CONDITION 733 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 734 RANGE('a', 'z') 735 END_ARGUMENT_CONDITION 736 RETURN_VALUE_CONDITION(WithinRange) 737 SINGLE_VALUE(0) 738 END_RETURN_VALUE_CONDITION 739 END_CASE 740 CASE // The locale-specific range. 741 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 742 RANGE(128, 255) 743 END_ARGUMENT_CONDITION 744 END_CASE 745 CASE // Is not an unsigned char. 746 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 747 RANGE(0, 255) 748 END_ARGUMENT_CONDITION 749 RETURN_VALUE_CONDITION(WithinRange) 750 SINGLE_VALUE(0) 751 END_RETURN_VALUE_CONDITION 752 END_CASE 753 END_SUMMARY 754 SUMMARY(isprint, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 755 INVALIDATION_APPROACH(EvalCallAsPure)) 756 CASE 757 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 758 RANGE(32, 126) 759 END_ARGUMENT_CONDITION 760 RETURN_VALUE_CONDITION(OutOfRange) 761 SINGLE_VALUE(0) 762 END_RETURN_VALUE_CONDITION 763 END_CASE 764 CASE 765 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 766 RANGE(32, 126) 767 END_ARGUMENT_CONDITION 768 RETURN_VALUE_CONDITION(WithinRange) 769 SINGLE_VALUE(0) 770 END_RETURN_VALUE_CONDITION 771 END_CASE 772 END_SUMMARY 773 SUMMARY(ispunct, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 774 INVALIDATION_APPROACH(EvalCallAsPure)) 775 CASE 776 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 777 RANGE('!', '/') 778 RANGE(':', '@') 779 RANGE('[', '`') 780 RANGE('{', '~') 781 END_ARGUMENT_CONDITION 782 RETURN_VALUE_CONDITION(OutOfRange) 783 SINGLE_VALUE(0) 784 END_RETURN_VALUE_CONDITION 785 END_CASE 786 CASE 787 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 788 RANGE('!', '/') 789 RANGE(':', '@') 790 RANGE('[', '`') 791 RANGE('{', '~') 792 END_ARGUMENT_CONDITION 793 RETURN_VALUE_CONDITION(WithinRange) 794 SINGLE_VALUE(0) 795 END_RETURN_VALUE_CONDITION 796 END_CASE 797 END_SUMMARY 798 SUMMARY(isspace, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 799 INVALIDATION_APPROACH(EvalCallAsPure)) 800 CASE // Space, '\f', '\n', '\r', '\t', '\v'. 801 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 802 RANGE(9, 13) 803 SINGLE_VALUE(' ') 804 END_ARGUMENT_CONDITION 805 RETURN_VALUE_CONDITION(OutOfRange) 806 SINGLE_VALUE(0) 807 END_RETURN_VALUE_CONDITION 808 END_CASE 809 CASE // The locale-specific range. 810 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 811 RANGE(128, 255) 812 END_ARGUMENT_CONDITION 813 END_CASE 814 CASE 815 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 816 RANGE(9, 13) 817 SINGLE_VALUE(' ') 818 RANGE(128, 255) 819 END_ARGUMENT_CONDITION 820 RETURN_VALUE_CONDITION(WithinRange) 821 SINGLE_VALUE(0) 822 END_RETURN_VALUE_CONDITION 823 END_CASE 824 END_SUMMARY 825 SUMMARY(isupper, ARGUMENT_TYPES(IntTy), RETURN_TYPE (IntTy), 826 INVALIDATION_APPROACH(EvalCallAsPure)) 827 CASE // Is certainly uppercase. 828 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 829 RANGE('A', 'Z') 830 END_ARGUMENT_CONDITION 831 RETURN_VALUE_CONDITION(OutOfRange) 832 SINGLE_VALUE(0) 833 END_RETURN_VALUE_CONDITION 834 END_CASE 835 CASE // The locale-specific range. 836 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 837 RANGE(128, 255) 838 END_ARGUMENT_CONDITION 839 END_CASE 840 CASE // Other. 841 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 842 RANGE('A', 'Z') RANGE(128, 255) 843 END_ARGUMENT_CONDITION 844 RETURN_VALUE_CONDITION(WithinRange) 845 SINGLE_VALUE(0) 846 END_RETURN_VALUE_CONDITION 847 END_CASE 848 END_SUMMARY 849 SUMMARY(isxdigit, ARGUMENT_TYPES(IntTy), RETURN_TYPE(IntTy), 850 INVALIDATION_APPROACH(EvalCallAsPure)) 851 CASE 852 ARGUMENT_CONDITION(ARG_NO(0), WithinRange) 853 RANGE('0', '9') 854 RANGE('A', 'F') 855 RANGE('a', 'f') 856 END_ARGUMENT_CONDITION 857 RETURN_VALUE_CONDITION(OutOfRange) 858 SINGLE_VALUE(0) 859 END_RETURN_VALUE_CONDITION 860 END_CASE 861 CASE 862 ARGUMENT_CONDITION(ARG_NO(0), OutOfRange) 863 RANGE('0', '9') 864 RANGE('A', 'F') 865 RANGE('a', 'f') 866 END_ARGUMENT_CONDITION 867 RETURN_VALUE_CONDITION(WithinRange) 868 SINGLE_VALUE(0) 869 END_RETURN_VALUE_CONDITION 870 END_CASE 871 END_SUMMARY 872 873 // The getc() family of functions that returns either a char or an EOF. 874 SUMMARY(getc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy), 875 INVALIDATION_APPROACH(NoEvalCall)) 876 CASE // FIXME: EOF is assumed to be defined as -1. 877 RETURN_VALUE_CONDITION(WithinRange) 878 RANGE(-1, 255) 879 END_RETURN_VALUE_CONDITION 880 END_CASE 881 END_SUMMARY 882 SUMMARY(fgetc, ARGUMENT_TYPES(Irrelevant), RETURN_TYPE(IntTy), 883 INVALIDATION_APPROACH(NoEvalCall)) 884 CASE // FIXME: EOF is assumed to be defined as -1. 885 RETURN_VALUE_CONDITION(WithinRange) 886 RANGE(-1, 255) 887 END_RETURN_VALUE_CONDITION 888 END_CASE 889 END_SUMMARY 890 SUMMARY(getchar, ARGUMENT_TYPES(), RETURN_TYPE(IntTy), 891 INVALIDATION_APPROACH(NoEvalCall)) 892 CASE // FIXME: EOF is assumed to be defined as -1. 893 RETURN_VALUE_CONDITION(WithinRange) 894 RANGE(-1, 255) 895 END_RETURN_VALUE_CONDITION 896 END_CASE 897 END_SUMMARY 898 899 // read()-like functions that never return more than buffer size. 900 // We are not sure how ssize_t is defined on every platform, so we provide 901 // three variants that should cover common cases. 902 SUMMARY_WITH_VARIANTS(read) 903 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 904 RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) 905 CASE 906 RETURN_VALUE_CONDITION(ComparesToArgument) 907 IS_LESS_THAN(ARG_NO(2)) 908 END_RETURN_VALUE_CONDITION 909 RETURN_VALUE_CONDITION(WithinRange) 910 RANGE(-1, IntMax) 911 END_RETURN_VALUE_CONDITION 912 END_CASE 913 END_VARIANT 914 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 915 RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) 916 CASE 917 RETURN_VALUE_CONDITION(ComparesToArgument) 918 IS_LESS_THAN(ARG_NO(2)) 919 END_RETURN_VALUE_CONDITION 920 RETURN_VALUE_CONDITION(WithinRange) 921 RANGE(-1, LongMax) 922 END_RETURN_VALUE_CONDITION 923 END_CASE 924 END_VARIANT 925 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 926 RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) 927 CASE 928 RETURN_VALUE_CONDITION(ComparesToArgument) 929 IS_LESS_THAN(ARG_NO(2)) 930 END_RETURN_VALUE_CONDITION 931 RETURN_VALUE_CONDITION(WithinRange) 932 RANGE(-1, LongLongMax) 933 END_RETURN_VALUE_CONDITION 934 END_CASE 935 END_VARIANT 936 END_SUMMARY_WITH_VARIANTS 937 SUMMARY_WITH_VARIANTS(write) 938 // Again, due to elusive nature of ssize_t, we have duplicate 939 // our summaries to cover different variants. 940 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 941 RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) 942 CASE 943 RETURN_VALUE_CONDITION(ComparesToArgument) 944 IS_LESS_THAN(ARG_NO(2)) 945 END_RETURN_VALUE_CONDITION 946 RETURN_VALUE_CONDITION(WithinRange) 947 RANGE(-1, IntMax) 948 END_RETURN_VALUE_CONDITION 949 END_CASE 950 END_VARIANT 951 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 952 RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) 953 CASE 954 RETURN_VALUE_CONDITION(ComparesToArgument) 955 IS_LESS_THAN(ARG_NO(2)) 956 END_RETURN_VALUE_CONDITION 957 RETURN_VALUE_CONDITION(WithinRange) 958 RANGE(-1, LongMax) 959 END_RETURN_VALUE_CONDITION 960 END_CASE 961 END_VARIANT 962 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy), 963 RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) 964 CASE 965 RETURN_VALUE_CONDITION(ComparesToArgument) 966 IS_LESS_THAN(ARG_NO(2)) 967 END_RETURN_VALUE_CONDITION 968 RETURN_VALUE_CONDITION(WithinRange) 969 RANGE(-1, LongLongMax) 970 END_RETURN_VALUE_CONDITION 971 END_CASE 972 END_VARIANT 973 END_SUMMARY_WITH_VARIANTS 974 SUMMARY(fread, 975 ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant), 976 RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall)) 977 CASE 978 RETURN_VALUE_CONDITION(ComparesToArgument) 979 IS_LESS_THAN(ARG_NO(2)) 980 END_RETURN_VALUE_CONDITION 981 END_CASE 982 END_SUMMARY 983 SUMMARY(fwrite, 984 ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant), 985 RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall)) 986 CASE 987 RETURN_VALUE_CONDITION(ComparesToArgument) 988 IS_LESS_THAN(ARG_NO(2)) 989 END_RETURN_VALUE_CONDITION 990 END_CASE 991 END_SUMMARY 992 993 // getline()-like functions either fail or read at least the delimiter. 994 SUMMARY_WITH_VARIANTS(getline) 995 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), 996 RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) 997 CASE 998 RETURN_VALUE_CONDITION(WithinRange) 999 SINGLE_VALUE(-1) 1000 RANGE(1, IntMax) 1001 END_RETURN_VALUE_CONDITION 1002 END_CASE 1003 END_VARIANT 1004 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), 1005 RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) 1006 CASE 1007 RETURN_VALUE_CONDITION(WithinRange) 1008 SINGLE_VALUE(-1) 1009 RANGE(1, LongMax) 1010 END_RETURN_VALUE_CONDITION 1011 END_CASE 1012 END_VARIANT 1013 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant), 1014 RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) 1015 CASE 1016 RETURN_VALUE_CONDITION(WithinRange) 1017 SINGLE_VALUE(-1) 1018 RANGE(1, LongLongMax) 1019 END_RETURN_VALUE_CONDITION 1020 END_CASE 1021 END_VARIANT 1022 END_SUMMARY_WITH_VARIANTS 1023 SUMMARY_WITH_VARIANTS(getdelim) 1024 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), 1025 RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall)) 1026 CASE 1027 RETURN_VALUE_CONDITION(WithinRange) 1028 SINGLE_VALUE(-1) 1029 RANGE(1, IntMax) 1030 END_RETURN_VALUE_CONDITION 1031 END_CASE 1032 END_VARIANT 1033 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), 1034 RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall)) 1035 CASE 1036 RETURN_VALUE_CONDITION(WithinRange) 1037 SINGLE_VALUE(-1) 1038 RANGE(1, LongMax) 1039 END_RETURN_VALUE_CONDITION 1040 END_CASE 1041 END_VARIANT 1042 VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant), 1043 RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall)) 1044 CASE 1045 RETURN_VALUE_CONDITION(WithinRange) 1046 SINGLE_VALUE(-1) 1047 RANGE(1, LongLongMax) 1048 END_RETURN_VALUE_CONDITION 1049 END_CASE 1050 END_VARIANT 1051 END_SUMMARY_WITH_VARIANTS 1052 }; 1053 } 1054 1055 void ento::registerStdCLibraryFunctionsChecker(CheckerManager &mgr) { 1056 // If this checker grows large enough to support C++, Objective-C, or other 1057 // standard libraries, we could use multiple register...Checker() functions, 1058 // which would register various checkers with the help of the same Checker 1059 // class, turning on different function summaries. 1060 mgr.registerChecker<StdLibraryFunctionsChecker>(); 1061 } 1062 1063 bool ento::shouldRegisterStdCLibraryFunctionsChecker(const LangOptions &LO) { 1064 return true; 1065 } 1066