1 //== PrintfFormatString.cpp - Analysis of printf 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 // Handling of format string in printf and friends. The structure of format 11 // strings for fprintf() are described in C99 7.19.6.1. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Analysis/Analyses/FormatString.h" 16 #include "FormatStringParsing.h" 17 #include "clang/Basic/TargetInfo.h" 18 19 using clang::analyze_format_string::ArgType; 20 using clang::analyze_format_string::FormatStringHandler; 21 using clang::analyze_format_string::LengthModifier; 22 using clang::analyze_format_string::OptionalAmount; 23 using clang::analyze_format_string::ConversionSpecifier; 24 using clang::analyze_printf::PrintfSpecifier; 25 26 using namespace clang; 27 28 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 29 PrintfSpecifierResult; 30 31 //===----------------------------------------------------------------------===// 32 // Methods for parsing format strings. 33 //===----------------------------------------------------------------------===// 34 35 using analyze_format_string::ParseNonPositionAmount; 36 37 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 38 const char *Start, const char *&Beg, const char *E, 39 unsigned *argIndex) { 40 if (argIndex) { 41 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 42 } else { 43 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 44 analyze_format_string::PrecisionPos); 45 if (Amt.isInvalid()) 46 return true; 47 FS.setPrecision(Amt); 48 } 49 return false; 50 } 51 52 static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS, 53 const char *FlagBeg, const char *E, bool Warn) { 54 StringRef Flag(FlagBeg, E - FlagBeg); 55 // Currently there is only one flag. 56 if (Flag == "tt") { 57 FS.setHasObjCTechnicalTerm(FlagBeg); 58 return false; 59 } 60 // Handle either the case of no flag or an invalid flag. 61 if (Warn) { 62 if (Flag == "") 63 H.HandleEmptyObjCModifierFlag(FlagBeg, E - FlagBeg); 64 else 65 H.HandleInvalidObjCModifierFlag(FlagBeg, E - FlagBeg); 66 } 67 return true; 68 } 69 70 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 71 const char *&Beg, 72 const char *E, 73 unsigned &argIndex, 74 const LangOptions &LO, 75 const TargetInfo &Target, 76 bool Warn, 77 bool isFreeBSDKPrintf) { 78 79 using namespace clang::analyze_format_string; 80 using namespace clang::analyze_printf; 81 82 const char *I = Beg; 83 const char *Start = nullptr; 84 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 85 86 // Look for a '%' character that indicates the start of a format specifier. 87 for ( ; I != E ; ++I) { 88 char c = *I; 89 if (c == '\0') { 90 // Detect spurious null characters, which are likely errors. 91 H.HandleNullChar(I); 92 return true; 93 } 94 if (c == '%') { 95 Start = I++; // Record the start of the format specifier. 96 break; 97 } 98 } 99 100 // No format specifier found? 101 if (!Start) 102 return false; 103 104 if (I == E) { 105 // No more characters left? 106 if (Warn) 107 H.HandleIncompleteSpecifier(Start, E - Start); 108 return true; 109 } 110 111 PrintfSpecifier FS; 112 if (ParseArgPosition(H, FS, Start, I, E)) 113 return true; 114 115 if (I == E) { 116 // No more characters left? 117 if (Warn) 118 H.HandleIncompleteSpecifier(Start, E - Start); 119 return true; 120 } 121 122 // Look for flags (if any). 123 bool hasMore = true; 124 for ( ; I != E; ++I) { 125 switch (*I) { 126 default: hasMore = false; break; 127 case '\'': 128 // FIXME: POSIX specific. Always accept? 129 FS.setHasThousandsGrouping(I); 130 break; 131 case '-': FS.setIsLeftJustified(I); break; 132 case '+': FS.setHasPlusPrefix(I); break; 133 case ' ': FS.setHasSpacePrefix(I); break; 134 case '#': FS.setHasAlternativeForm(I); break; 135 case '0': FS.setHasLeadingZeros(I); break; 136 } 137 if (!hasMore) 138 break; 139 } 140 141 if (I == E) { 142 // No more characters left? 143 if (Warn) 144 H.HandleIncompleteSpecifier(Start, E - Start); 145 return true; 146 } 147 148 // Look for the field width (if any). 149 if (ParseFieldWidth(H, FS, Start, I, E, 150 FS.usesPositionalArg() ? nullptr : &argIndex)) 151 return true; 152 153 if (I == E) { 154 // No more characters left? 155 if (Warn) 156 H.HandleIncompleteSpecifier(Start, E - Start); 157 return true; 158 } 159 160 // Look for the precision (if any). 161 if (*I == '.') { 162 ++I; 163 if (I == E) { 164 if (Warn) 165 H.HandleIncompleteSpecifier(Start, E - Start); 166 return true; 167 } 168 169 if (ParsePrecision(H, FS, Start, I, E, 170 FS.usesPositionalArg() ? nullptr : &argIndex)) 171 return true; 172 173 if (I == E) { 174 // No more characters left? 175 if (Warn) 176 H.HandleIncompleteSpecifier(Start, E - Start); 177 return true; 178 } 179 } 180 181 // Look for the length modifier. 182 if (ParseLengthModifier(FS, I, E, LO) && I == E) { 183 // No more characters left? 184 if (Warn) 185 H.HandleIncompleteSpecifier(Start, E - Start); 186 return true; 187 } 188 189 // Look for the Objective-C modifier flags, if any. 190 // We parse these here, even if they don't apply to 191 // the conversion specifier, and then emit an error 192 // later if the conversion specifier isn't '@'. This 193 // enables better recovery, and we don't know if 194 // these flags are applicable until later. 195 const char *ObjCModifierFlagsStart = nullptr, 196 *ObjCModifierFlagsEnd = nullptr; 197 if (*I == '[') { 198 ObjCModifierFlagsStart = I; 199 ++I; 200 auto flagStart = I; 201 for (;; ++I) { 202 ObjCModifierFlagsEnd = I; 203 if (I == E) { 204 if (Warn) 205 H.HandleIncompleteSpecifier(Start, E - Start); 206 return true; 207 } 208 // Did we find the closing ']'? 209 if (*I == ']') { 210 if (ParseObjCFlags(H, FS, flagStart, I, Warn)) 211 return true; 212 ++I; 213 break; 214 } 215 // There are no separators defined yet for multiple 216 // Objective-C modifier flags. When those are 217 // defined, this is the place to check. 218 } 219 } 220 221 if (*I == '\0') { 222 // Detect spurious null characters, which are likely errors. 223 H.HandleNullChar(I); 224 return true; 225 } 226 227 // Finally, look for the conversion specifier. 228 const char *conversionPosition = I++; 229 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 230 switch (*conversionPosition) { 231 default: 232 break; 233 // C99: 7.19.6.1 (section 8). 234 case '%': k = ConversionSpecifier::PercentArg; break; 235 case 'A': k = ConversionSpecifier::AArg; break; 236 case 'E': k = ConversionSpecifier::EArg; break; 237 case 'F': k = ConversionSpecifier::FArg; break; 238 case 'G': k = ConversionSpecifier::GArg; break; 239 case 'X': k = ConversionSpecifier::XArg; break; 240 case 'a': k = ConversionSpecifier::aArg; break; 241 case 'c': k = ConversionSpecifier::cArg; break; 242 case 'd': k = ConversionSpecifier::dArg; break; 243 case 'e': k = ConversionSpecifier::eArg; break; 244 case 'f': k = ConversionSpecifier::fArg; break; 245 case 'g': k = ConversionSpecifier::gArg; break; 246 case 'i': k = ConversionSpecifier::iArg; break; 247 case 'n': k = ConversionSpecifier::nArg; break; 248 case 'o': k = ConversionSpecifier::oArg; break; 249 case 'p': k = ConversionSpecifier::pArg; break; 250 case 's': k = ConversionSpecifier::sArg; break; 251 case 'u': k = ConversionSpecifier::uArg; break; 252 case 'x': k = ConversionSpecifier::xArg; break; 253 // POSIX specific. 254 case 'C': k = ConversionSpecifier::CArg; break; 255 case 'S': k = ConversionSpecifier::SArg; break; 256 // Objective-C. 257 case '@': k = ConversionSpecifier::ObjCObjArg; break; 258 // Glibc specific. 259 case 'm': k = ConversionSpecifier::PrintErrno; break; 260 // FreeBSD kernel specific. 261 case 'b': 262 if (isFreeBSDKPrintf) 263 k = ConversionSpecifier::FreeBSDbArg; // int followed by char * 264 break; 265 case 'r': 266 if (isFreeBSDKPrintf) 267 k = ConversionSpecifier::FreeBSDrArg; // int 268 break; 269 case 'y': 270 if (isFreeBSDKPrintf) 271 k = ConversionSpecifier::FreeBSDyArg; // int 272 break; 273 // Apple-specific. 274 case 'D': 275 if (isFreeBSDKPrintf) 276 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * 277 else if (Target.getTriple().isOSDarwin()) 278 k = ConversionSpecifier::DArg; 279 break; 280 case 'O': 281 if (Target.getTriple().isOSDarwin()) 282 k = ConversionSpecifier::OArg; 283 break; 284 case 'U': 285 if (Target.getTriple().isOSDarwin()) 286 k = ConversionSpecifier::UArg; 287 break; 288 // MS specific. 289 case 'Z': 290 if (Target.getTriple().isOSMSVCRT()) 291 k = ConversionSpecifier::ZArg; 292 } 293 294 // Check to see if we used the Objective-C modifier flags with 295 // a conversion specifier other than '@'. 296 if (k != ConversionSpecifier::ObjCObjArg && 297 k != ConversionSpecifier::InvalidSpecifier && 298 ObjCModifierFlagsStart) { 299 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, 300 ObjCModifierFlagsEnd + 1, 301 conversionPosition); 302 return true; 303 } 304 305 PrintfConversionSpecifier CS(conversionPosition, k); 306 FS.setConversionSpecifier(CS); 307 if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 308 FS.setArgIndex(argIndex++); 309 // FreeBSD kernel specific. 310 if (k == ConversionSpecifier::FreeBSDbArg || 311 k == ConversionSpecifier::FreeBSDDArg) 312 argIndex++; 313 314 if (k == ConversionSpecifier::InvalidSpecifier) { 315 unsigned Len = I - Start; 316 if (ParseUTF8InvalidSpecifier(Start, E, Len)) { 317 CS.setEndScanList(Start + Len); 318 FS.setConversionSpecifier(CS); 319 } 320 // Assume the conversion takes one argument. 321 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); 322 } 323 return PrintfSpecifierResult(Start, FS); 324 } 325 326 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 327 const char *I, 328 const char *E, 329 const LangOptions &LO, 330 const TargetInfo &Target, 331 bool isFreeBSDKPrintf) { 332 333 unsigned argIndex = 0; 334 335 // Keep looking for a format specifier until we have exhausted the string. 336 while (I != E) { 337 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 338 LO, Target, true, 339 isFreeBSDKPrintf); 340 // Did a fail-stop error of any kind occur when parsing the specifier? 341 // If so, don't do any more processing. 342 if (FSR.shouldStop()) 343 return true; 344 // Did we exhaust the string or encounter an error that 345 // we can recover from? 346 if (!FSR.hasValue()) 347 continue; 348 // We have a format specifier. Pass it to the callback. 349 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 350 I - FSR.getStart())) 351 return true; 352 } 353 assert(I == E && "Format string not exhausted"); 354 return false; 355 } 356 357 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, 358 const char *E, 359 const LangOptions &LO, 360 const TargetInfo &Target) { 361 362 unsigned argIndex = 0; 363 364 // Keep looking for a %s format specifier until we have exhausted the string. 365 FormatStringHandler H; 366 while (I != E) { 367 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 368 LO, Target, false, 369 false); 370 // Did a fail-stop error of any kind occur when parsing the specifier? 371 // If so, don't do any more processing. 372 if (FSR.shouldStop()) 373 return false; 374 // Did we exhaust the string or encounter an error that 375 // we can recover from? 376 if (!FSR.hasValue()) 377 continue; 378 const analyze_printf::PrintfSpecifier &FS = FSR.getValue(); 379 // Return true if this a %s format specifier. 380 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg) 381 return true; 382 } 383 return false; 384 } 385 386 //===----------------------------------------------------------------------===// 387 // Methods on PrintfSpecifier. 388 //===----------------------------------------------------------------------===// 389 390 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 391 bool IsObjCLiteral) const { 392 const PrintfConversionSpecifier &CS = getConversionSpecifier(); 393 394 if (!CS.consumesDataArgument()) 395 return ArgType::Invalid(); 396 397 if (CS.getKind() == ConversionSpecifier::cArg) 398 switch (LM.getKind()) { 399 case LengthModifier::None: 400 return Ctx.IntTy; 401 case LengthModifier::AsLong: 402 case LengthModifier::AsWide: 403 return ArgType(ArgType::WIntTy, "wint_t"); 404 case LengthModifier::AsShort: 405 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) 406 return Ctx.IntTy; 407 default: 408 return ArgType::Invalid(); 409 } 410 411 if (CS.isIntArg()) 412 switch (LM.getKind()) { 413 case LengthModifier::AsLongDouble: 414 // GNU extension. 415 return Ctx.LongLongTy; 416 case LengthModifier::None: 417 return Ctx.IntTy; 418 case LengthModifier::AsInt32: 419 return ArgType(Ctx.IntTy, "__int32"); 420 case LengthModifier::AsChar: return ArgType::AnyCharTy; 421 case LengthModifier::AsShort: return Ctx.ShortTy; 422 case LengthModifier::AsLong: return Ctx.LongTy; 423 case LengthModifier::AsLongLong: 424 case LengthModifier::AsQuad: 425 return Ctx.LongLongTy; 426 case LengthModifier::AsInt64: 427 return ArgType(Ctx.LongLongTy, "__int64"); 428 case LengthModifier::AsIntMax: 429 return ArgType(Ctx.getIntMaxType(), "intmax_t"); 430 case LengthModifier::AsSizeT: 431 // FIXME: How to get the corresponding signed version of size_t? 432 return ArgType(); 433 case LengthModifier::AsInt3264: 434 return Ctx.getTargetInfo().getTriple().isArch64Bit() 435 ? ArgType(Ctx.LongLongTy, "__int64") 436 : ArgType(Ctx.IntTy, "__int32"); 437 case LengthModifier::AsPtrDiff: 438 return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); 439 case LengthModifier::AsAllocate: 440 case LengthModifier::AsMAllocate: 441 case LengthModifier::AsWide: 442 return ArgType::Invalid(); 443 } 444 445 if (CS.isUIntArg()) 446 switch (LM.getKind()) { 447 case LengthModifier::AsLongDouble: 448 // GNU extension. 449 return Ctx.UnsignedLongLongTy; 450 case LengthModifier::None: 451 return Ctx.UnsignedIntTy; 452 case LengthModifier::AsInt32: 453 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 454 case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 455 case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 456 case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 457 case LengthModifier::AsLongLong: 458 case LengthModifier::AsQuad: 459 return Ctx.UnsignedLongLongTy; 460 case LengthModifier::AsInt64: 461 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); 462 case LengthModifier::AsIntMax: 463 return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 464 case LengthModifier::AsSizeT: 465 return ArgType(Ctx.getSizeType(), "size_t"); 466 case LengthModifier::AsInt3264: 467 return Ctx.getTargetInfo().getTriple().isArch64Bit() 468 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") 469 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 470 case LengthModifier::AsPtrDiff: 471 // FIXME: How to get the corresponding unsigned 472 // version of ptrdiff_t? 473 return ArgType(); 474 case LengthModifier::AsAllocate: 475 case LengthModifier::AsMAllocate: 476 case LengthModifier::AsWide: 477 return ArgType::Invalid(); 478 } 479 480 if (CS.isDoubleArg()) { 481 if (LM.getKind() == LengthModifier::AsLongDouble) 482 return Ctx.LongDoubleTy; 483 return Ctx.DoubleTy; 484 } 485 486 if (CS.getKind() == ConversionSpecifier::nArg) { 487 switch (LM.getKind()) { 488 case LengthModifier::None: 489 return ArgType::PtrTo(Ctx.IntTy); 490 case LengthModifier::AsChar: 491 return ArgType::PtrTo(Ctx.SignedCharTy); 492 case LengthModifier::AsShort: 493 return ArgType::PtrTo(Ctx.ShortTy); 494 case LengthModifier::AsLong: 495 return ArgType::PtrTo(Ctx.LongTy); 496 case LengthModifier::AsLongLong: 497 case LengthModifier::AsQuad: 498 return ArgType::PtrTo(Ctx.LongLongTy); 499 case LengthModifier::AsIntMax: 500 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 501 case LengthModifier::AsSizeT: 502 return ArgType(); // FIXME: ssize_t 503 case LengthModifier::AsPtrDiff: 504 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 505 case LengthModifier::AsLongDouble: 506 return ArgType(); // FIXME: Is this a known extension? 507 case LengthModifier::AsAllocate: 508 case LengthModifier::AsMAllocate: 509 case LengthModifier::AsInt32: 510 case LengthModifier::AsInt3264: 511 case LengthModifier::AsInt64: 512 case LengthModifier::AsWide: 513 return ArgType::Invalid(); 514 } 515 } 516 517 switch (CS.getKind()) { 518 case ConversionSpecifier::sArg: 519 if (LM.getKind() == LengthModifier::AsWideChar) { 520 if (IsObjCLiteral) 521 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 522 "const unichar *"); 523 return ArgType(ArgType::WCStrTy, "wchar_t *"); 524 } 525 if (LM.getKind() == LengthModifier::AsWide) 526 return ArgType(ArgType::WCStrTy, "wchar_t *"); 527 return ArgType::CStrTy; 528 case ConversionSpecifier::SArg: 529 if (IsObjCLiteral) 530 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 531 "const unichar *"); 532 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 533 LM.getKind() == LengthModifier::AsShort) 534 return ArgType::CStrTy; 535 return ArgType(ArgType::WCStrTy, "wchar_t *"); 536 case ConversionSpecifier::CArg: 537 if (IsObjCLiteral) 538 return ArgType(Ctx.UnsignedShortTy, "unichar"); 539 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 540 LM.getKind() == LengthModifier::AsShort) 541 return Ctx.IntTy; 542 return ArgType(Ctx.WideCharTy, "wchar_t"); 543 case ConversionSpecifier::pArg: 544 return ArgType::CPointerTy; 545 case ConversionSpecifier::ObjCObjArg: 546 return ArgType::ObjCPointerTy; 547 default: 548 break; 549 } 550 551 // FIXME: Handle other cases. 552 return ArgType(); 553 } 554 555 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 556 ASTContext &Ctx, bool IsObjCLiteral) { 557 // %n is different from other conversion specifiers; don't try to fix it. 558 if (CS.getKind() == ConversionSpecifier::nArg) 559 return false; 560 561 // Handle Objective-C objects first. Note that while the '%@' specifier will 562 // not warn for structure pointer or void pointer arguments (because that's 563 // how CoreFoundation objects are implemented), we only show a fixit for '%@' 564 // if we know it's an object (block, id, class, or __attribute__((NSObject))). 565 if (QT->isObjCRetainableType()) { 566 if (!IsObjCLiteral) 567 return false; 568 569 CS.setKind(ConversionSpecifier::ObjCObjArg); 570 571 // Disable irrelevant flags 572 HasThousandsGrouping = false; 573 HasPlusPrefix = false; 574 HasSpacePrefix = false; 575 HasAlternativeForm = false; 576 HasLeadingZeroes = false; 577 Precision.setHowSpecified(OptionalAmount::NotSpecified); 578 LM.setKind(LengthModifier::None); 579 580 return true; 581 } 582 583 // Handle strings next (char *, wchar_t *) 584 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 585 CS.setKind(ConversionSpecifier::sArg); 586 587 // Disable irrelevant flags 588 HasAlternativeForm = 0; 589 HasLeadingZeroes = 0; 590 591 // Set the long length modifier for wide characters 592 if (QT->getPointeeType()->isWideCharType()) 593 LM.setKind(LengthModifier::AsWideChar); 594 else 595 LM.setKind(LengthModifier::None); 596 597 return true; 598 } 599 600 // If it's an enum, get its underlying type. 601 if (const EnumType *ETy = QT->getAs<EnumType>()) 602 QT = ETy->getDecl()->getIntegerType(); 603 604 // We can only work with builtin types. 605 const BuiltinType *BT = QT->getAs<BuiltinType>(); 606 if (!BT) 607 return false; 608 609 // Set length modifier 610 switch (BT->getKind()) { 611 case BuiltinType::Bool: 612 case BuiltinType::WChar_U: 613 case BuiltinType::WChar_S: 614 case BuiltinType::Char16: 615 case BuiltinType::Char32: 616 case BuiltinType::UInt128: 617 case BuiltinType::Int128: 618 case BuiltinType::Half: 619 case BuiltinType::Float128: 620 // Various types which are non-trivial to correct. 621 return false; 622 623 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 624 case BuiltinType::Id: 625 #include "clang/Basic/OpenCLImageTypes.def" 626 #define SIGNED_TYPE(Id, SingletonId) 627 #define UNSIGNED_TYPE(Id, SingletonId) 628 #define FLOATING_TYPE(Id, SingletonId) 629 #define BUILTIN_TYPE(Id, SingletonId) \ 630 case BuiltinType::Id: 631 #include "clang/AST/BuiltinTypes.def" 632 // Misc other stuff which doesn't make sense here. 633 return false; 634 635 case BuiltinType::UInt: 636 case BuiltinType::Int: 637 case BuiltinType::Float: 638 case BuiltinType::Double: 639 LM.setKind(LengthModifier::None); 640 break; 641 642 case BuiltinType::Char_U: 643 case BuiltinType::UChar: 644 case BuiltinType::Char_S: 645 case BuiltinType::SChar: 646 LM.setKind(LengthModifier::AsChar); 647 break; 648 649 case BuiltinType::Short: 650 case BuiltinType::UShort: 651 LM.setKind(LengthModifier::AsShort); 652 break; 653 654 case BuiltinType::Long: 655 case BuiltinType::ULong: 656 LM.setKind(LengthModifier::AsLong); 657 break; 658 659 case BuiltinType::LongLong: 660 case BuiltinType::ULongLong: 661 LM.setKind(LengthModifier::AsLongLong); 662 break; 663 664 case BuiltinType::LongDouble: 665 LM.setKind(LengthModifier::AsLongDouble); 666 break; 667 } 668 669 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 670 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 671 namedTypeToLengthModifier(QT, LM); 672 673 // If fixing the length modifier was enough, we might be done. 674 if (hasValidLengthModifier(Ctx.getTargetInfo())) { 675 // If we're going to offer a fix anyway, make sure the sign matches. 676 switch (CS.getKind()) { 677 case ConversionSpecifier::uArg: 678 case ConversionSpecifier::UArg: 679 if (QT->isSignedIntegerType()) 680 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); 681 break; 682 case ConversionSpecifier::dArg: 683 case ConversionSpecifier::DArg: 684 case ConversionSpecifier::iArg: 685 if (QT->isUnsignedIntegerType() && !HasPlusPrefix) 686 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); 687 break; 688 default: 689 // Other specifiers do not have signed/unsigned variants. 690 break; 691 } 692 693 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 694 if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 695 return true; 696 } 697 698 // Set conversion specifier and disable any flags which do not apply to it. 699 // Let typedefs to char fall through to int, as %c is silly for uint8_t. 700 if (!isa<TypedefType>(QT) && QT->isCharType()) { 701 CS.setKind(ConversionSpecifier::cArg); 702 LM.setKind(LengthModifier::None); 703 Precision.setHowSpecified(OptionalAmount::NotSpecified); 704 HasAlternativeForm = 0; 705 HasLeadingZeroes = 0; 706 HasPlusPrefix = 0; 707 } 708 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 709 else if (QT->isRealFloatingType()) { 710 CS.setKind(ConversionSpecifier::fArg); 711 } 712 else if (QT->isSignedIntegerType()) { 713 CS.setKind(ConversionSpecifier::dArg); 714 HasAlternativeForm = 0; 715 } 716 else if (QT->isUnsignedIntegerType()) { 717 CS.setKind(ConversionSpecifier::uArg); 718 HasAlternativeForm = 0; 719 HasPlusPrefix = 0; 720 } else { 721 llvm_unreachable("Unexpected type"); 722 } 723 724 return true; 725 } 726 727 void PrintfSpecifier::toString(raw_ostream &os) const { 728 // Whilst some features have no defined order, we are using the order 729 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 730 os << "%"; 731 732 // Positional args 733 if (usesPositionalArg()) { 734 os << getPositionalArgIndex() << "$"; 735 } 736 737 // Conversion flags 738 if (IsLeftJustified) os << "-"; 739 if (HasPlusPrefix) os << "+"; 740 if (HasSpacePrefix) os << " "; 741 if (HasAlternativeForm) os << "#"; 742 if (HasLeadingZeroes) os << "0"; 743 744 // Minimum field width 745 FieldWidth.toString(os); 746 // Precision 747 Precision.toString(os); 748 // Length modifier 749 os << LM.toString(); 750 // Conversion specifier 751 os << CS.toString(); 752 } 753 754 bool PrintfSpecifier::hasValidPlusPrefix() const { 755 if (!HasPlusPrefix) 756 return true; 757 758 // The plus prefix only makes sense for signed conversions 759 switch (CS.getKind()) { 760 case ConversionSpecifier::dArg: 761 case ConversionSpecifier::DArg: 762 case ConversionSpecifier::iArg: 763 case ConversionSpecifier::fArg: 764 case ConversionSpecifier::FArg: 765 case ConversionSpecifier::eArg: 766 case ConversionSpecifier::EArg: 767 case ConversionSpecifier::gArg: 768 case ConversionSpecifier::GArg: 769 case ConversionSpecifier::aArg: 770 case ConversionSpecifier::AArg: 771 case ConversionSpecifier::FreeBSDrArg: 772 case ConversionSpecifier::FreeBSDyArg: 773 return true; 774 775 default: 776 return false; 777 } 778 } 779 780 bool PrintfSpecifier::hasValidAlternativeForm() const { 781 if (!HasAlternativeForm) 782 return true; 783 784 // Alternate form flag only valid with the oxXaAeEfFgG conversions 785 switch (CS.getKind()) { 786 case ConversionSpecifier::oArg: 787 case ConversionSpecifier::OArg: 788 case ConversionSpecifier::xArg: 789 case ConversionSpecifier::XArg: 790 case ConversionSpecifier::aArg: 791 case ConversionSpecifier::AArg: 792 case ConversionSpecifier::eArg: 793 case ConversionSpecifier::EArg: 794 case ConversionSpecifier::fArg: 795 case ConversionSpecifier::FArg: 796 case ConversionSpecifier::gArg: 797 case ConversionSpecifier::GArg: 798 case ConversionSpecifier::FreeBSDrArg: 799 case ConversionSpecifier::FreeBSDyArg: 800 return true; 801 802 default: 803 return false; 804 } 805 } 806 807 bool PrintfSpecifier::hasValidLeadingZeros() const { 808 if (!HasLeadingZeroes) 809 return true; 810 811 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 812 switch (CS.getKind()) { 813 case ConversionSpecifier::dArg: 814 case ConversionSpecifier::DArg: 815 case ConversionSpecifier::iArg: 816 case ConversionSpecifier::oArg: 817 case ConversionSpecifier::OArg: 818 case ConversionSpecifier::uArg: 819 case ConversionSpecifier::UArg: 820 case ConversionSpecifier::xArg: 821 case ConversionSpecifier::XArg: 822 case ConversionSpecifier::aArg: 823 case ConversionSpecifier::AArg: 824 case ConversionSpecifier::eArg: 825 case ConversionSpecifier::EArg: 826 case ConversionSpecifier::fArg: 827 case ConversionSpecifier::FArg: 828 case ConversionSpecifier::gArg: 829 case ConversionSpecifier::GArg: 830 case ConversionSpecifier::FreeBSDrArg: 831 case ConversionSpecifier::FreeBSDyArg: 832 return true; 833 834 default: 835 return false; 836 } 837 } 838 839 bool PrintfSpecifier::hasValidSpacePrefix() const { 840 if (!HasSpacePrefix) 841 return true; 842 843 // The space prefix only makes sense for signed conversions 844 switch (CS.getKind()) { 845 case ConversionSpecifier::dArg: 846 case ConversionSpecifier::DArg: 847 case ConversionSpecifier::iArg: 848 case ConversionSpecifier::fArg: 849 case ConversionSpecifier::FArg: 850 case ConversionSpecifier::eArg: 851 case ConversionSpecifier::EArg: 852 case ConversionSpecifier::gArg: 853 case ConversionSpecifier::GArg: 854 case ConversionSpecifier::aArg: 855 case ConversionSpecifier::AArg: 856 case ConversionSpecifier::FreeBSDrArg: 857 case ConversionSpecifier::FreeBSDyArg: 858 return true; 859 860 default: 861 return false; 862 } 863 } 864 865 bool PrintfSpecifier::hasValidLeftJustified() const { 866 if (!IsLeftJustified) 867 return true; 868 869 // The left justified flag is valid for all conversions except n 870 switch (CS.getKind()) { 871 case ConversionSpecifier::nArg: 872 return false; 873 874 default: 875 return true; 876 } 877 } 878 879 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 880 if (!HasThousandsGrouping) 881 return true; 882 883 switch (CS.getKind()) { 884 case ConversionSpecifier::dArg: 885 case ConversionSpecifier::DArg: 886 case ConversionSpecifier::iArg: 887 case ConversionSpecifier::uArg: 888 case ConversionSpecifier::UArg: 889 case ConversionSpecifier::fArg: 890 case ConversionSpecifier::FArg: 891 case ConversionSpecifier::gArg: 892 case ConversionSpecifier::GArg: 893 return true; 894 default: 895 return false; 896 } 897 } 898 899 bool PrintfSpecifier::hasValidPrecision() const { 900 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 901 return true; 902 903 // Precision is only valid with the diouxXaAeEfFgGs conversions 904 switch (CS.getKind()) { 905 case ConversionSpecifier::dArg: 906 case ConversionSpecifier::DArg: 907 case ConversionSpecifier::iArg: 908 case ConversionSpecifier::oArg: 909 case ConversionSpecifier::OArg: 910 case ConversionSpecifier::uArg: 911 case ConversionSpecifier::UArg: 912 case ConversionSpecifier::xArg: 913 case ConversionSpecifier::XArg: 914 case ConversionSpecifier::aArg: 915 case ConversionSpecifier::AArg: 916 case ConversionSpecifier::eArg: 917 case ConversionSpecifier::EArg: 918 case ConversionSpecifier::fArg: 919 case ConversionSpecifier::FArg: 920 case ConversionSpecifier::gArg: 921 case ConversionSpecifier::GArg: 922 case ConversionSpecifier::sArg: 923 case ConversionSpecifier::FreeBSDrArg: 924 case ConversionSpecifier::FreeBSDyArg: 925 return true; 926 927 default: 928 return false; 929 } 930 } 931 bool PrintfSpecifier::hasValidFieldWidth() const { 932 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 933 return true; 934 935 // The field width is valid for all conversions except n 936 switch (CS.getKind()) { 937 case ConversionSpecifier::nArg: 938 return false; 939 940 default: 941 return true; 942 } 943 } 944