1 //= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines APIs for analyzing the format strings of printf, fscanf, 11 // and friends. 12 // 13 // The structure of format strings for fprintf are described in C99 7.19.6.1. 14 // 15 // The structure of format strings for fscanf are described in C99 7.19.6.2. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H 20 #define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H 21 22 #include "clang/AST/CanonicalType.h" 23 24 namespace clang { 25 26 class TargetInfo; 27 28 //===----------------------------------------------------------------------===// 29 /// Common components of both fprintf and fscanf format strings. 30 namespace analyze_format_string { 31 32 /// Class representing optional flags with location and representation 33 /// information. 34 class OptionalFlag { 35 public: OptionalFlag(const char * Representation)36 OptionalFlag(const char *Representation) 37 : representation(Representation), flag(false) {} isSet()38 bool isSet() { return flag; } set()39 void set() { flag = true; } clear()40 void clear() { flag = false; } setPosition(const char * position)41 void setPosition(const char *position) { 42 assert(position); 43 flag = true; 44 this->position = position; 45 } getPosition()46 const char *getPosition() const { 47 assert(position); 48 return position; 49 } toString()50 const char *toString() const { return representation; } 51 52 // Overloaded operators for bool like qualities 53 explicit operator bool() const { return flag; } 54 OptionalFlag& operator=(const bool &rhs) { 55 flag = rhs; 56 return *this; // Return a reference to myself. 57 } 58 private: 59 const char *representation; 60 const char *position; 61 bool flag; 62 }; 63 64 /// Represents the length modifier in a format string in scanf/printf. 65 class LengthModifier { 66 public: 67 enum Kind { 68 None, 69 AsChar, // 'hh' 70 AsShort, // 'h' 71 AsLong, // 'l' 72 AsLongLong, // 'll' 73 AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types) 74 AsIntMax, // 'j' 75 AsSizeT, // 'z' 76 AsPtrDiff, // 't' 77 AsInt32, // 'I32' (MSVCRT, like __int32) 78 AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL) 79 AsInt64, // 'I64' (MSVCRT, like __int64) 80 AsLongDouble, // 'L' 81 AsAllocate, // for '%as', GNU extension to C90 scanf 82 AsMAllocate, // for '%ms', GNU extension to scanf 83 AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z 84 AsWideChar = AsLong // for '%ls', only makes sense for printf 85 }; 86 LengthModifier()87 LengthModifier() 88 : Position(nullptr), kind(None) {} LengthModifier(const char * pos,Kind k)89 LengthModifier(const char *pos, Kind k) 90 : Position(pos), kind(k) {} 91 getStart()92 const char *getStart() const { 93 return Position; 94 } 95 getLength()96 unsigned getLength() const { 97 switch (kind) { 98 default: 99 return 1; 100 case AsLongLong: 101 case AsChar: 102 return 2; 103 case AsInt32: 104 case AsInt64: 105 return 3; 106 case None: 107 return 0; 108 } 109 } 110 getKind()111 Kind getKind() const { return kind; } setKind(Kind k)112 void setKind(Kind k) { kind = k; } 113 114 const char *toString() const; 115 116 private: 117 const char *Position; 118 Kind kind; 119 }; 120 121 class ConversionSpecifier { 122 public: 123 enum Kind { 124 InvalidSpecifier = 0, 125 // C99 conversion specifiers. 126 cArg, 127 dArg, 128 DArg, // Apple extension 129 iArg, 130 IntArgBeg = dArg, IntArgEnd = iArg, 131 132 oArg, 133 OArg, // Apple extension 134 uArg, 135 UArg, // Apple extension 136 xArg, 137 XArg, 138 UIntArgBeg = oArg, UIntArgEnd = XArg, 139 140 fArg, 141 FArg, 142 eArg, 143 EArg, 144 gArg, 145 GArg, 146 aArg, 147 AArg, 148 DoubleArgBeg = fArg, DoubleArgEnd = AArg, 149 150 sArg, 151 pArg, 152 nArg, 153 PercentArg, 154 CArg, 155 SArg, 156 157 // ** Printf-specific ** 158 159 ZArg, // MS extension 160 161 // Objective-C specific specifiers. 162 ObjCObjArg, // '@' 163 ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, 164 165 // FreeBSD kernel specific specifiers. 166 FreeBSDbArg, 167 FreeBSDDArg, 168 FreeBSDrArg, 169 FreeBSDyArg, 170 171 // GlibC specific specifiers. 172 PrintErrno, // 'm' 173 174 PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno, 175 176 // ** Scanf-specific ** 177 ScanListArg, // '[' 178 ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg 179 }; 180 181 ConversionSpecifier(bool isPrintf = true) IsPrintf(isPrintf)182 : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr), 183 kind(InvalidSpecifier) {} 184 ConversionSpecifier(bool isPrintf,const char * pos,Kind k)185 ConversionSpecifier(bool isPrintf, const char *pos, Kind k) 186 : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {} 187 getStart()188 const char *getStart() const { 189 return Position; 190 } 191 getCharacters()192 StringRef getCharacters() const { 193 return StringRef(getStart(), getLength()); 194 } 195 consumesDataArgument()196 bool consumesDataArgument() const { 197 switch (kind) { 198 case PrintErrno: 199 assert(IsPrintf); 200 return false; 201 case PercentArg: 202 return false; 203 default: 204 return true; 205 } 206 } 207 getKind()208 Kind getKind() const { return kind; } setKind(Kind k)209 void setKind(Kind k) { kind = k; } getLength()210 unsigned getLength() const { 211 return EndScanList ? EndScanList - Position : 1; 212 } setEndScanList(const char * pos)213 void setEndScanList(const char *pos) { EndScanList = pos; } 214 isIntArg()215 bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) || 216 kind == FreeBSDrArg || kind == FreeBSDyArg; } isUIntArg()217 bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } isAnyIntArg()218 bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } isDoubleArg()219 bool isDoubleArg() const { 220 return kind >= DoubleArgBeg && kind <= DoubleArgEnd; 221 } 222 223 const char *toString() const; 224 isPrintfKind()225 bool isPrintfKind() const { return IsPrintf; } 226 227 Optional<ConversionSpecifier> getStandardSpecifier() const; 228 229 protected: 230 bool IsPrintf; 231 const char *Position; 232 const char *EndScanList; 233 Kind kind; 234 }; 235 236 class ArgType { 237 public: 238 enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, 239 AnyCharTy, CStrTy, WCStrTy, WIntTy }; 240 241 enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic }; 242 243 private: 244 const Kind K; 245 QualType T; 246 const char *Name; 247 bool Ptr; 248 public: 249 ArgType(Kind k = UnknownTy, const char *n = nullptr) K(k)250 : K(k), Name(n), Ptr(false) {} 251 ArgType(QualType t, const char *n = nullptr) K(SpecificTy)252 : K(SpecificTy), T(t), Name(n), Ptr(false) {} ArgType(CanQualType t)253 ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {} 254 Invalid()255 static ArgType Invalid() { return ArgType(InvalidTy); } isValid()256 bool isValid() const { return K != InvalidTy; } 257 258 /// Create an ArgType which corresponds to the type pointer to A. PtrTo(const ArgType & A)259 static ArgType PtrTo(const ArgType& A) { 260 assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); 261 ArgType Res = A; 262 Res.Ptr = true; 263 return Res; 264 } 265 266 MatchKind matchesType(ASTContext &C, QualType argTy) const; 267 268 QualType getRepresentativeType(ASTContext &C) const; 269 270 std::string getRepresentativeTypeName(ASTContext &C) const; 271 }; 272 273 class OptionalAmount { 274 public: 275 enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; 276 OptionalAmount(HowSpecified howSpecified,unsigned amount,const char * amountStart,unsigned amountLength,bool usesPositionalArg)277 OptionalAmount(HowSpecified howSpecified, 278 unsigned amount, 279 const char *amountStart, 280 unsigned amountLength, 281 bool usesPositionalArg) 282 : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), 283 UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} 284 285 OptionalAmount(bool valid = true) start(nullptr)286 : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), 287 UsesPositionalArg(0), UsesDotPrefix(0) {} 288 isInvalid()289 bool isInvalid() const { 290 return hs == Invalid; 291 } 292 getHowSpecified()293 HowSpecified getHowSpecified() const { return hs; } setHowSpecified(HowSpecified h)294 void setHowSpecified(HowSpecified h) { hs = h; } 295 hasDataArgument()296 bool hasDataArgument() const { return hs == Arg; } 297 getArgIndex()298 unsigned getArgIndex() const { 299 assert(hasDataArgument()); 300 return amt; 301 } 302 getConstantAmount()303 unsigned getConstantAmount() const { 304 assert(hs == Constant); 305 return amt; 306 } 307 getStart()308 const char *getStart() const { 309 // We include the . character if it is given. 310 return start - UsesDotPrefix; 311 } 312 getConstantLength()313 unsigned getConstantLength() const { 314 assert(hs == Constant); 315 return length + UsesDotPrefix; 316 } 317 318 ArgType getArgType(ASTContext &Ctx) const; 319 320 void toString(raw_ostream &os) const; 321 usesPositionalArg()322 bool usesPositionalArg() const { return (bool) UsesPositionalArg; } getPositionalArgIndex()323 unsigned getPositionalArgIndex() const { 324 assert(hasDataArgument()); 325 return amt + 1; 326 } 327 usesDotPrefix()328 bool usesDotPrefix() const { return UsesDotPrefix; } setUsesDotPrefix()329 void setUsesDotPrefix() { UsesDotPrefix = true; } 330 331 private: 332 const char *start; 333 unsigned length; 334 HowSpecified hs; 335 unsigned amt; 336 bool UsesPositionalArg : 1; 337 bool UsesDotPrefix; 338 }; 339 340 341 class FormatSpecifier { 342 protected: 343 LengthModifier LM; 344 OptionalAmount FieldWidth; 345 ConversionSpecifier CS; 346 /// Positional arguments, an IEEE extension: 347 /// IEEE Std 1003.1, 2004 Edition 348 /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html 349 bool UsesPositionalArg; 350 unsigned argIndex; 351 public: FormatSpecifier(bool isPrintf)352 FormatSpecifier(bool isPrintf) 353 : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {} 354 setLengthModifier(LengthModifier lm)355 void setLengthModifier(LengthModifier lm) { 356 LM = lm; 357 } 358 setUsesPositionalArg()359 void setUsesPositionalArg() { UsesPositionalArg = true; } 360 setArgIndex(unsigned i)361 void setArgIndex(unsigned i) { 362 argIndex = i; 363 } 364 getArgIndex()365 unsigned getArgIndex() const { 366 return argIndex; 367 } 368 getPositionalArgIndex()369 unsigned getPositionalArgIndex() const { 370 return argIndex + 1; 371 } 372 getLengthModifier()373 const LengthModifier &getLengthModifier() const { 374 return LM; 375 } 376 getFieldWidth()377 const OptionalAmount &getFieldWidth() const { 378 return FieldWidth; 379 } 380 setFieldWidth(const OptionalAmount & Amt)381 void setFieldWidth(const OptionalAmount &Amt) { 382 FieldWidth = Amt; 383 } 384 usesPositionalArg()385 bool usesPositionalArg() const { return UsesPositionalArg; } 386 387 bool hasValidLengthModifier(const TargetInfo &Target) const; 388 389 bool hasStandardLengthModifier() const; 390 391 Optional<LengthModifier> getCorrectedLengthModifier() const; 392 393 bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; 394 395 bool hasStandardLengthConversionCombination() const; 396 397 /// For a TypedefType QT, if it is a named integer type such as size_t, 398 /// assign the appropriate value to LM and return true. 399 static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); 400 }; 401 402 } // end analyze_format_string namespace 403 404 //===----------------------------------------------------------------------===// 405 /// Pieces specific to fprintf format strings. 406 407 namespace analyze_printf { 408 409 class PrintfConversionSpecifier : 410 public analyze_format_string::ConversionSpecifier { 411 public: PrintfConversionSpecifier()412 PrintfConversionSpecifier() 413 : ConversionSpecifier(true, nullptr, InvalidSpecifier) {} 414 PrintfConversionSpecifier(const char * pos,Kind k)415 PrintfConversionSpecifier(const char *pos, Kind k) 416 : ConversionSpecifier(true, pos, k) {} 417 isObjCArg()418 bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } isDoubleArg()419 bool isDoubleArg() const { return kind >= DoubleArgBeg && 420 kind <= DoubleArgEnd; } 421 classof(const analyze_format_string::ConversionSpecifier * CS)422 static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 423 return CS->isPrintfKind(); 424 } 425 }; 426 427 using analyze_format_string::ArgType; 428 using analyze_format_string::LengthModifier; 429 using analyze_format_string::OptionalAmount; 430 using analyze_format_string::OptionalFlag; 431 432 class PrintfSpecifier : public analyze_format_string::FormatSpecifier { 433 OptionalFlag HasThousandsGrouping; // ''', POSIX extension. 434 OptionalFlag IsLeftJustified; // '-' 435 OptionalFlag HasPlusPrefix; // '+' 436 OptionalFlag HasSpacePrefix; // ' ' 437 OptionalFlag HasAlternativeForm; // '#' 438 OptionalFlag HasLeadingZeroes; // '0' 439 OptionalFlag HasObjCTechnicalTerm; // '[tt]' 440 OptionalAmount Precision; 441 public: PrintfSpecifier()442 PrintfSpecifier() : 443 FormatSpecifier(/* isPrintf = */ true), 444 HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"), 445 HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0"), 446 HasObjCTechnicalTerm("tt") {} 447 448 static PrintfSpecifier Parse(const char *beg, const char *end); 449 450 // Methods for incrementally constructing the PrintfSpecifier. setConversionSpecifier(const PrintfConversionSpecifier & cs)451 void setConversionSpecifier(const PrintfConversionSpecifier &cs) { 452 CS = cs; 453 } setHasThousandsGrouping(const char * position)454 void setHasThousandsGrouping(const char *position) { 455 HasThousandsGrouping.setPosition(position); 456 } setIsLeftJustified(const char * position)457 void setIsLeftJustified(const char *position) { 458 IsLeftJustified.setPosition(position); 459 } setHasPlusPrefix(const char * position)460 void setHasPlusPrefix(const char *position) { 461 HasPlusPrefix.setPosition(position); 462 } setHasSpacePrefix(const char * position)463 void setHasSpacePrefix(const char *position) { 464 HasSpacePrefix.setPosition(position); 465 } setHasAlternativeForm(const char * position)466 void setHasAlternativeForm(const char *position) { 467 HasAlternativeForm.setPosition(position); 468 } setHasLeadingZeros(const char * position)469 void setHasLeadingZeros(const char *position) { 470 HasLeadingZeroes.setPosition(position); 471 } setHasObjCTechnicalTerm(const char * position)472 void setHasObjCTechnicalTerm(const char *position) { 473 HasObjCTechnicalTerm.setPosition(position); 474 } setUsesPositionalArg()475 void setUsesPositionalArg() { UsesPositionalArg = true; } 476 477 // Methods for querying the format specifier. 478 getConversionSpecifier()479 const PrintfConversionSpecifier &getConversionSpecifier() const { 480 return cast<PrintfConversionSpecifier>(CS); 481 } 482 setPrecision(const OptionalAmount & Amt)483 void setPrecision(const OptionalAmount &Amt) { 484 Precision = Amt; 485 Precision.setUsesDotPrefix(); 486 } 487 getPrecision()488 const OptionalAmount &getPrecision() const { 489 return Precision; 490 } 491 consumesDataArgument()492 bool consumesDataArgument() const { 493 return getConversionSpecifier().consumesDataArgument(); 494 } 495 496 /// \brief Returns the builtin type that a data argument 497 /// paired with this format specifier should have. This method 498 /// will return null if the format specifier does not have 499 /// a matching data argument or the matching argument matches 500 /// more than one type. 501 ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; 502 hasThousandsGrouping()503 const OptionalFlag &hasThousandsGrouping() const { 504 return HasThousandsGrouping; 505 } isLeftJustified()506 const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } hasPlusPrefix()507 const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } hasAlternativeForm()508 const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } hasLeadingZeros()509 const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } hasSpacePrefix()510 const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } hasObjCTechnicalTerm()511 const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; } usesPositionalArg()512 bool usesPositionalArg() const { return UsesPositionalArg; } 513 514 /// Changes the specifier and length according to a QualType, retaining any 515 /// flags or options. Returns true on success, or false when a conversion 516 /// was not successful. 517 bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, 518 bool IsObjCLiteral); 519 520 void toString(raw_ostream &os) const; 521 522 // Validation methods - to check if any element results in undefined behavior 523 bool hasValidPlusPrefix() const; 524 bool hasValidAlternativeForm() const; 525 bool hasValidLeadingZeros() const; 526 bool hasValidSpacePrefix() const; 527 bool hasValidLeftJustified() const; 528 bool hasValidThousandsGroupingPrefix() const; 529 530 bool hasValidPrecision() const; 531 bool hasValidFieldWidth() const; 532 }; 533 } // end analyze_printf namespace 534 535 //===----------------------------------------------------------------------===// 536 /// Pieces specific to fscanf format strings. 537 538 namespace analyze_scanf { 539 540 class ScanfConversionSpecifier : 541 public analyze_format_string::ConversionSpecifier { 542 public: ScanfConversionSpecifier()543 ScanfConversionSpecifier() 544 : ConversionSpecifier(false, nullptr, InvalidSpecifier) {} 545 ScanfConversionSpecifier(const char * pos,Kind k)546 ScanfConversionSpecifier(const char *pos, Kind k) 547 : ConversionSpecifier(false, pos, k) {} 548 classof(const analyze_format_string::ConversionSpecifier * CS)549 static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 550 return !CS->isPrintfKind(); 551 } 552 }; 553 554 using analyze_format_string::ArgType; 555 using analyze_format_string::LengthModifier; 556 using analyze_format_string::OptionalAmount; 557 using analyze_format_string::OptionalFlag; 558 559 class ScanfSpecifier : public analyze_format_string::FormatSpecifier { 560 OptionalFlag SuppressAssignment; // '*' 561 public: ScanfSpecifier()562 ScanfSpecifier() : 563 FormatSpecifier(/* isPrintf = */ false), 564 SuppressAssignment("*") {} 565 setSuppressAssignment(const char * position)566 void setSuppressAssignment(const char *position) { 567 SuppressAssignment.setPosition(position); 568 } 569 getSuppressAssignment()570 const OptionalFlag &getSuppressAssignment() const { 571 return SuppressAssignment; 572 } 573 setConversionSpecifier(const ScanfConversionSpecifier & cs)574 void setConversionSpecifier(const ScanfConversionSpecifier &cs) { 575 CS = cs; 576 } 577 getConversionSpecifier()578 const ScanfConversionSpecifier &getConversionSpecifier() const { 579 return cast<ScanfConversionSpecifier>(CS); 580 } 581 consumesDataArgument()582 bool consumesDataArgument() const { 583 return CS.consumesDataArgument() && !SuppressAssignment; 584 } 585 586 ArgType getArgType(ASTContext &Ctx) const; 587 588 bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, 589 ASTContext &Ctx); 590 591 void toString(raw_ostream &os) const; 592 593 static ScanfSpecifier Parse(const char *beg, const char *end); 594 }; 595 596 } // end analyze_scanf namespace 597 598 //===----------------------------------------------------------------------===// 599 // Parsing and processing of format strings (both fprintf and fscanf). 600 601 namespace analyze_format_string { 602 603 enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; 604 605 class FormatStringHandler { 606 public: FormatStringHandler()607 FormatStringHandler() {} 608 virtual ~FormatStringHandler(); 609 HandleNullChar(const char * nullCharacter)610 virtual void HandleNullChar(const char *nullCharacter) {} 611 HandlePosition(const char * startPos,unsigned posLen)612 virtual void HandlePosition(const char *startPos, unsigned posLen) {} 613 HandleInvalidPosition(const char * startPos,unsigned posLen,PositionContext p)614 virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, 615 PositionContext p) {} 616 HandleZeroPosition(const char * startPos,unsigned posLen)617 virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} 618 HandleIncompleteSpecifier(const char * startSpecifier,unsigned specifierLen)619 virtual void HandleIncompleteSpecifier(const char *startSpecifier, 620 unsigned specifierLen) {} 621 HandleEmptyObjCModifierFlag(const char * startFlags,unsigned flagsLen)622 virtual void HandleEmptyObjCModifierFlag(const char *startFlags, 623 unsigned flagsLen) {} 624 HandleInvalidObjCModifierFlag(const char * startFlag,unsigned flagLen)625 virtual void HandleInvalidObjCModifierFlag(const char *startFlag, 626 unsigned flagLen) {} 627 HandleObjCFlagsWithNonObjCConversion(const char * flagsStart,const char * flagsEnd,const char * conversionPosition)628 virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, 629 const char *flagsEnd, 630 const char *conversionPosition) {} 631 // Printf-specific handlers. 632 HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)633 virtual bool HandleInvalidPrintfConversionSpecifier( 634 const analyze_printf::PrintfSpecifier &FS, 635 const char *startSpecifier, 636 unsigned specifierLen) { 637 return true; 638 } 639 HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)640 virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, 641 const char *startSpecifier, 642 unsigned specifierLen) { 643 return true; 644 } 645 646 // Scanf-specific handlers. 647 HandleInvalidScanfConversionSpecifier(const analyze_scanf::ScanfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)648 virtual bool HandleInvalidScanfConversionSpecifier( 649 const analyze_scanf::ScanfSpecifier &FS, 650 const char *startSpecifier, 651 unsigned specifierLen) { 652 return true; 653 } 654 HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)655 virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, 656 const char *startSpecifier, 657 unsigned specifierLen) { 658 return true; 659 } 660 HandleIncompleteScanList(const char * start,const char * end)661 virtual void HandleIncompleteScanList(const char *start, const char *end) {} 662 }; 663 664 bool ParsePrintfString(FormatStringHandler &H, 665 const char *beg, const char *end, const LangOptions &LO, 666 const TargetInfo &Target, bool isFreeBSDKPrintf); 667 668 bool ParseFormatStringHasSArg(const char *beg, const char *end, 669 const LangOptions &LO, const TargetInfo &Target); 670 671 bool ParseScanfString(FormatStringHandler &H, 672 const char *beg, const char *end, const LangOptions &LO, 673 const TargetInfo &Target); 674 675 } // end analyze_format_string namespace 676 } // end clang namespace 677 #endif 678