1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- 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 // Handling of format string in printf and friends. The structure of format 10 // strings for fprintf() are described in C99 7.19.6.1. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/FormatString.h" 15 #include "clang/AST/OSLog.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 if (*I == '{') { 123 ++I; 124 unsigned char PrivacyFlags = 0; 125 StringRef MatchedStr; 126 127 do { 128 StringRef Str(I, E - I); 129 std::string Match = "^[[:space:]]*" 130 "(private|public|sensitive|mask\\.[^[:space:],}]*)" 131 "[[:space:]]*(,|})"; 132 llvm::Regex R(Match); 133 SmallVector<StringRef, 2> Matches; 134 135 if (R.match(Str, &Matches)) { 136 MatchedStr = Matches[1]; 137 I += Matches[0].size(); 138 139 // Set the privacy flag if the privacy annotation in the 140 // comma-delimited segment is at least as strict as the privacy 141 // annotations in previous comma-delimited segments. 142 if (MatchedStr.startswith("mask")) { 143 StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1); 144 unsigned Size = MaskType.size(); 145 if (Warn && (Size == 0 || Size > 8)) 146 H.handleInvalidMaskType(MaskType); 147 FS.setMaskType(MaskType); 148 } else if (MatchedStr.equals("sensitive")) 149 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive; 150 else if (PrivacyFlags != 151 clang::analyze_os_log::OSLogBufferItem::IsSensitive && 152 MatchedStr.equals("private")) 153 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate; 154 else if (PrivacyFlags == 0 && MatchedStr.equals("public")) 155 PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic; 156 } else { 157 size_t CommaOrBracePos = 158 Str.find_if([](char c) { return c == ',' || c == '}'; }); 159 160 if (CommaOrBracePos == StringRef::npos) { 161 // Neither a comma nor the closing brace was found. 162 if (Warn) 163 H.HandleIncompleteSpecifier(Start, E - Start); 164 return true; 165 } 166 167 I += CommaOrBracePos + 1; 168 } 169 // Continue until the closing brace is found. 170 } while (*(I - 1) == ','); 171 172 // Set the privacy flag. 173 switch (PrivacyFlags) { 174 case 0: 175 break; 176 case clang::analyze_os_log::OSLogBufferItem::IsPrivate: 177 FS.setIsPrivate(MatchedStr.data()); 178 break; 179 case clang::analyze_os_log::OSLogBufferItem::IsPublic: 180 FS.setIsPublic(MatchedStr.data()); 181 break; 182 case clang::analyze_os_log::OSLogBufferItem::IsSensitive: 183 FS.setIsSensitive(MatchedStr.data()); 184 break; 185 default: 186 llvm_unreachable("Unexpected privacy flag value"); 187 } 188 } 189 190 // Look for flags (if any). 191 bool hasMore = true; 192 for ( ; I != E; ++I) { 193 switch (*I) { 194 default: hasMore = false; break; 195 case '\'': 196 // FIXME: POSIX specific. Always accept? 197 FS.setHasThousandsGrouping(I); 198 break; 199 case '-': FS.setIsLeftJustified(I); break; 200 case '+': FS.setHasPlusPrefix(I); break; 201 case ' ': FS.setHasSpacePrefix(I); break; 202 case '#': FS.setHasAlternativeForm(I); break; 203 case '0': FS.setHasLeadingZeros(I); break; 204 } 205 if (!hasMore) 206 break; 207 } 208 209 if (I == E) { 210 // No more characters left? 211 if (Warn) 212 H.HandleIncompleteSpecifier(Start, E - Start); 213 return true; 214 } 215 216 // Look for the field width (if any). 217 if (ParseFieldWidth(H, FS, Start, I, E, 218 FS.usesPositionalArg() ? nullptr : &argIndex)) 219 return true; 220 221 if (I == E) { 222 // No more characters left? 223 if (Warn) 224 H.HandleIncompleteSpecifier(Start, E - Start); 225 return true; 226 } 227 228 // Look for the precision (if any). 229 if (*I == '.') { 230 ++I; 231 if (I == E) { 232 if (Warn) 233 H.HandleIncompleteSpecifier(Start, E - Start); 234 return true; 235 } 236 237 if (ParsePrecision(H, FS, Start, I, E, 238 FS.usesPositionalArg() ? nullptr : &argIndex)) 239 return true; 240 241 if (I == E) { 242 // No more characters left? 243 if (Warn) 244 H.HandleIncompleteSpecifier(Start, E - Start); 245 return true; 246 } 247 } 248 249 if (ParseVectorModifier(H, FS, I, E, LO)) 250 return true; 251 252 // Look for the length modifier. 253 if (ParseLengthModifier(FS, I, E, LO) && I == E) { 254 // No more characters left? 255 if (Warn) 256 H.HandleIncompleteSpecifier(Start, E - Start); 257 return true; 258 } 259 260 // Look for the Objective-C modifier flags, if any. 261 // We parse these here, even if they don't apply to 262 // the conversion specifier, and then emit an error 263 // later if the conversion specifier isn't '@'. This 264 // enables better recovery, and we don't know if 265 // these flags are applicable until later. 266 const char *ObjCModifierFlagsStart = nullptr, 267 *ObjCModifierFlagsEnd = nullptr; 268 if (*I == '[') { 269 ObjCModifierFlagsStart = I; 270 ++I; 271 auto flagStart = I; 272 for (;; ++I) { 273 ObjCModifierFlagsEnd = I; 274 if (I == E) { 275 if (Warn) 276 H.HandleIncompleteSpecifier(Start, E - Start); 277 return true; 278 } 279 // Did we find the closing ']'? 280 if (*I == ']') { 281 if (ParseObjCFlags(H, FS, flagStart, I, Warn)) 282 return true; 283 ++I; 284 break; 285 } 286 // There are no separators defined yet for multiple 287 // Objective-C modifier flags. When those are 288 // defined, this is the place to check. 289 } 290 } 291 292 if (*I == '\0') { 293 // Detect spurious null characters, which are likely errors. 294 H.HandleNullChar(I); 295 return true; 296 } 297 298 // Finally, look for the conversion specifier. 299 const char *conversionPosition = I++; 300 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 301 switch (*conversionPosition) { 302 default: 303 break; 304 // C99: 7.19.6.1 (section 8). 305 case '%': k = ConversionSpecifier::PercentArg; break; 306 case 'A': k = ConversionSpecifier::AArg; break; 307 case 'E': k = ConversionSpecifier::EArg; break; 308 case 'F': k = ConversionSpecifier::FArg; break; 309 case 'G': k = ConversionSpecifier::GArg; break; 310 case 'X': k = ConversionSpecifier::XArg; break; 311 case 'a': k = ConversionSpecifier::aArg; break; 312 case 'c': k = ConversionSpecifier::cArg; break; 313 case 'd': k = ConversionSpecifier::dArg; break; 314 case 'e': k = ConversionSpecifier::eArg; break; 315 case 'f': k = ConversionSpecifier::fArg; break; 316 case 'g': k = ConversionSpecifier::gArg; break; 317 case 'i': k = ConversionSpecifier::iArg; break; 318 case 'n': k = ConversionSpecifier::nArg; break; 319 case 'o': k = ConversionSpecifier::oArg; break; 320 case 'p': k = ConversionSpecifier::pArg; break; 321 case 's': k = ConversionSpecifier::sArg; break; 322 case 'u': k = ConversionSpecifier::uArg; break; 323 case 'x': k = ConversionSpecifier::xArg; break; 324 // POSIX specific. 325 case 'C': k = ConversionSpecifier::CArg; break; 326 case 'S': k = ConversionSpecifier::SArg; break; 327 // Apple extension for os_log 328 case 'P': 329 k = ConversionSpecifier::PArg; 330 break; 331 // Objective-C. 332 case '@': k = ConversionSpecifier::ObjCObjArg; break; 333 // Glibc specific. 334 case 'm': k = ConversionSpecifier::PrintErrno; break; 335 // FreeBSD kernel specific. 336 case 'b': 337 if (isFreeBSDKPrintf) 338 k = ConversionSpecifier::FreeBSDbArg; // int followed by char * 339 break; 340 case 'r': 341 if (isFreeBSDKPrintf) 342 k = ConversionSpecifier::FreeBSDrArg; // int 343 break; 344 case 'y': 345 if (isFreeBSDKPrintf) 346 k = ConversionSpecifier::FreeBSDyArg; // int 347 break; 348 // Apple-specific. 349 case 'D': 350 if (isFreeBSDKPrintf) 351 k = ConversionSpecifier::FreeBSDDArg; // void * followed by char * 352 else if (Target.getTriple().isOSDarwin()) 353 k = ConversionSpecifier::DArg; 354 break; 355 case 'O': 356 if (Target.getTriple().isOSDarwin()) 357 k = ConversionSpecifier::OArg; 358 break; 359 case 'U': 360 if (Target.getTriple().isOSDarwin()) 361 k = ConversionSpecifier::UArg; 362 break; 363 // MS specific. 364 case 'Z': 365 if (Target.getTriple().isOSMSVCRT()) 366 k = ConversionSpecifier::ZArg; 367 break; 368 } 369 370 // Check to see if we used the Objective-C modifier flags with 371 // a conversion specifier other than '@'. 372 if (k != ConversionSpecifier::ObjCObjArg && 373 k != ConversionSpecifier::InvalidSpecifier && 374 ObjCModifierFlagsStart) { 375 H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart, 376 ObjCModifierFlagsEnd + 1, 377 conversionPosition); 378 return true; 379 } 380 381 PrintfConversionSpecifier CS(conversionPosition, k); 382 FS.setConversionSpecifier(CS); 383 if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 384 FS.setArgIndex(argIndex++); 385 // FreeBSD kernel specific. 386 if (k == ConversionSpecifier::FreeBSDbArg || 387 k == ConversionSpecifier::FreeBSDDArg) 388 argIndex++; 389 390 if (k == ConversionSpecifier::InvalidSpecifier) { 391 unsigned Len = I - Start; 392 if (ParseUTF8InvalidSpecifier(Start, E, Len)) { 393 CS.setEndScanList(Start + Len); 394 FS.setConversionSpecifier(CS); 395 } 396 // Assume the conversion takes one argument. 397 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len); 398 } 399 return PrintfSpecifierResult(Start, FS); 400 } 401 402 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 403 const char *I, 404 const char *E, 405 const LangOptions &LO, 406 const TargetInfo &Target, 407 bool isFreeBSDKPrintf) { 408 409 unsigned argIndex = 0; 410 411 // Keep looking for a format specifier until we have exhausted the string. 412 while (I != E) { 413 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 414 LO, Target, true, 415 isFreeBSDKPrintf); 416 // Did a fail-stop error of any kind occur when parsing the specifier? 417 // If so, don't do any more processing. 418 if (FSR.shouldStop()) 419 return true; 420 // Did we exhaust the string or encounter an error that 421 // we can recover from? 422 if (!FSR.hasValue()) 423 continue; 424 // We have a format specifier. Pass it to the callback. 425 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 426 I - FSR.getStart())) 427 return true; 428 } 429 assert(I == E && "Format string not exhausted"); 430 return false; 431 } 432 433 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I, 434 const char *E, 435 const LangOptions &LO, 436 const TargetInfo &Target) { 437 438 unsigned argIndex = 0; 439 440 // Keep looking for a %s format specifier until we have exhausted the string. 441 FormatStringHandler H; 442 while (I != E) { 443 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 444 LO, Target, false, 445 false); 446 // Did a fail-stop error of any kind occur when parsing the specifier? 447 // If so, don't do any more processing. 448 if (FSR.shouldStop()) 449 return false; 450 // Did we exhaust the string or encounter an error that 451 // we can recover from? 452 if (!FSR.hasValue()) 453 continue; 454 const analyze_printf::PrintfSpecifier &FS = FSR.getValue(); 455 // Return true if this a %s format specifier. 456 if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg) 457 return true; 458 } 459 return false; 460 } 461 462 //===----------------------------------------------------------------------===// 463 // Methods on PrintfSpecifier. 464 //===----------------------------------------------------------------------===// 465 466 ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx, 467 bool IsObjCLiteral) const { 468 if (CS.getKind() == ConversionSpecifier::cArg) 469 switch (LM.getKind()) { 470 case LengthModifier::None: 471 return Ctx.IntTy; 472 case LengthModifier::AsLong: 473 case LengthModifier::AsWide: 474 return ArgType(ArgType::WIntTy, "wint_t"); 475 case LengthModifier::AsShort: 476 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT()) 477 return Ctx.IntTy; 478 LLVM_FALLTHROUGH; 479 default: 480 return ArgType::Invalid(); 481 } 482 483 if (CS.isIntArg()) 484 switch (LM.getKind()) { 485 case LengthModifier::AsLongDouble: 486 // GNU extension. 487 return Ctx.LongLongTy; 488 case LengthModifier::None: 489 return Ctx.IntTy; 490 case LengthModifier::AsInt32: 491 return ArgType(Ctx.IntTy, "__int32"); 492 case LengthModifier::AsChar: return ArgType::AnyCharTy; 493 case LengthModifier::AsShort: return Ctx.ShortTy; 494 case LengthModifier::AsLong: return Ctx.LongTy; 495 case LengthModifier::AsLongLong: 496 case LengthModifier::AsQuad: 497 return Ctx.LongLongTy; 498 case LengthModifier::AsInt64: 499 return ArgType(Ctx.LongLongTy, "__int64"); 500 case LengthModifier::AsIntMax: 501 return ArgType(Ctx.getIntMaxType(), "intmax_t"); 502 case LengthModifier::AsSizeT: 503 return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t")); 504 case LengthModifier::AsInt3264: 505 return Ctx.getTargetInfo().getTriple().isArch64Bit() 506 ? ArgType(Ctx.LongLongTy, "__int64") 507 : ArgType(Ctx.IntTy, "__int32"); 508 case LengthModifier::AsPtrDiff: 509 return ArgType::makePtrdiffT( 510 ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 511 case LengthModifier::AsAllocate: 512 case LengthModifier::AsMAllocate: 513 case LengthModifier::AsWide: 514 return ArgType::Invalid(); 515 } 516 517 if (CS.isUIntArg()) 518 switch (LM.getKind()) { 519 case LengthModifier::AsLongDouble: 520 // GNU extension. 521 return Ctx.UnsignedLongLongTy; 522 case LengthModifier::None: 523 return Ctx.UnsignedIntTy; 524 case LengthModifier::AsInt32: 525 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 526 case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 527 case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 528 case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 529 case LengthModifier::AsLongLong: 530 case LengthModifier::AsQuad: 531 return Ctx.UnsignedLongLongTy; 532 case LengthModifier::AsInt64: 533 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); 534 case LengthModifier::AsIntMax: 535 return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 536 case LengthModifier::AsSizeT: 537 return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t")); 538 case LengthModifier::AsInt3264: 539 return Ctx.getTargetInfo().getTriple().isArch64Bit() 540 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") 541 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 542 case LengthModifier::AsPtrDiff: 543 return ArgType::makePtrdiffT( 544 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t")); 545 case LengthModifier::AsAllocate: 546 case LengthModifier::AsMAllocate: 547 case LengthModifier::AsWide: 548 return ArgType::Invalid(); 549 } 550 551 if (CS.isDoubleArg()) { 552 if (LM.getKind() == LengthModifier::AsLongDouble) 553 return Ctx.LongDoubleTy; 554 return Ctx.DoubleTy; 555 } 556 557 if (CS.getKind() == ConversionSpecifier::nArg) { 558 switch (LM.getKind()) { 559 case LengthModifier::None: 560 return ArgType::PtrTo(Ctx.IntTy); 561 case LengthModifier::AsChar: 562 return ArgType::PtrTo(Ctx.SignedCharTy); 563 case LengthModifier::AsShort: 564 return ArgType::PtrTo(Ctx.ShortTy); 565 case LengthModifier::AsLong: 566 return ArgType::PtrTo(Ctx.LongTy); 567 case LengthModifier::AsLongLong: 568 case LengthModifier::AsQuad: 569 return ArgType::PtrTo(Ctx.LongLongTy); 570 case LengthModifier::AsIntMax: 571 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 572 case LengthModifier::AsSizeT: 573 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t")); 574 case LengthModifier::AsPtrDiff: 575 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 576 case LengthModifier::AsLongDouble: 577 return ArgType(); // FIXME: Is this a known extension? 578 case LengthModifier::AsAllocate: 579 case LengthModifier::AsMAllocate: 580 case LengthModifier::AsInt32: 581 case LengthModifier::AsInt3264: 582 case LengthModifier::AsInt64: 583 case LengthModifier::AsWide: 584 return ArgType::Invalid(); 585 } 586 } 587 588 switch (CS.getKind()) { 589 case ConversionSpecifier::sArg: 590 if (LM.getKind() == LengthModifier::AsWideChar) { 591 if (IsObjCLiteral) 592 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 593 "const unichar *"); 594 return ArgType(ArgType::WCStrTy, "wchar_t *"); 595 } 596 if (LM.getKind() == LengthModifier::AsWide) 597 return ArgType(ArgType::WCStrTy, "wchar_t *"); 598 return ArgType::CStrTy; 599 case ConversionSpecifier::SArg: 600 if (IsObjCLiteral) 601 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 602 "const unichar *"); 603 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 604 LM.getKind() == LengthModifier::AsShort) 605 return ArgType::CStrTy; 606 return ArgType(ArgType::WCStrTy, "wchar_t *"); 607 case ConversionSpecifier::CArg: 608 if (IsObjCLiteral) 609 return ArgType(Ctx.UnsignedShortTy, "unichar"); 610 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() && 611 LM.getKind() == LengthModifier::AsShort) 612 return Ctx.IntTy; 613 return ArgType(Ctx.WideCharTy, "wchar_t"); 614 case ConversionSpecifier::pArg: 615 case ConversionSpecifier::PArg: 616 return ArgType::CPointerTy; 617 case ConversionSpecifier::ObjCObjArg: 618 return ArgType::ObjCPointerTy; 619 default: 620 break; 621 } 622 623 // FIXME: Handle other cases. 624 return ArgType(); 625 } 626 627 628 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 629 bool IsObjCLiteral) const { 630 const PrintfConversionSpecifier &CS = getConversionSpecifier(); 631 632 if (!CS.consumesDataArgument()) 633 return ArgType::Invalid(); 634 635 ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral); 636 if (!ScalarTy.isValid() || VectorNumElts.isInvalid()) 637 return ScalarTy; 638 639 return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount()); 640 } 641 642 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 643 ASTContext &Ctx, bool IsObjCLiteral) { 644 // %n is different from other conversion specifiers; don't try to fix it. 645 if (CS.getKind() == ConversionSpecifier::nArg) 646 return false; 647 648 // Handle Objective-C objects first. Note that while the '%@' specifier will 649 // not warn for structure pointer or void pointer arguments (because that's 650 // how CoreFoundation objects are implemented), we only show a fixit for '%@' 651 // if we know it's an object (block, id, class, or __attribute__((NSObject))). 652 if (QT->isObjCRetainableType()) { 653 if (!IsObjCLiteral) 654 return false; 655 656 CS.setKind(ConversionSpecifier::ObjCObjArg); 657 658 // Disable irrelevant flags 659 HasThousandsGrouping = false; 660 HasPlusPrefix = false; 661 HasSpacePrefix = false; 662 HasAlternativeForm = false; 663 HasLeadingZeroes = false; 664 Precision.setHowSpecified(OptionalAmount::NotSpecified); 665 LM.setKind(LengthModifier::None); 666 667 return true; 668 } 669 670 // Handle strings next (char *, wchar_t *) 671 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 672 CS.setKind(ConversionSpecifier::sArg); 673 674 // Disable irrelevant flags 675 HasAlternativeForm = 0; 676 HasLeadingZeroes = 0; 677 678 // Set the long length modifier for wide characters 679 if (QT->getPointeeType()->isWideCharType()) 680 LM.setKind(LengthModifier::AsWideChar); 681 else 682 LM.setKind(LengthModifier::None); 683 684 return true; 685 } 686 687 // If it's an enum, get its underlying type. 688 if (const EnumType *ETy = QT->getAs<EnumType>()) 689 QT = ETy->getDecl()->getIntegerType(); 690 691 const BuiltinType *BT = QT->getAs<BuiltinType>(); 692 if (!BT) { 693 const VectorType *VT = QT->getAs<VectorType>(); 694 if (VT) { 695 QT = VT->getElementType(); 696 BT = QT->getAs<BuiltinType>(); 697 VectorNumElts = OptionalAmount(VT->getNumElements()); 698 } 699 } 700 701 // We can only work with builtin types. 702 if (!BT) 703 return false; 704 705 // Set length modifier 706 switch (BT->getKind()) { 707 case BuiltinType::Bool: 708 case BuiltinType::WChar_U: 709 case BuiltinType::WChar_S: 710 case BuiltinType::Char8: // FIXME: Treat like 'char'? 711 case BuiltinType::Char16: 712 case BuiltinType::Char32: 713 case BuiltinType::UInt128: 714 case BuiltinType::Int128: 715 case BuiltinType::Half: 716 case BuiltinType::Float16: 717 case BuiltinType::Float128: 718 case BuiltinType::ShortAccum: 719 case BuiltinType::Accum: 720 case BuiltinType::LongAccum: 721 case BuiltinType::UShortAccum: 722 case BuiltinType::UAccum: 723 case BuiltinType::ULongAccum: 724 case BuiltinType::ShortFract: 725 case BuiltinType::Fract: 726 case BuiltinType::LongFract: 727 case BuiltinType::UShortFract: 728 case BuiltinType::UFract: 729 case BuiltinType::ULongFract: 730 case BuiltinType::SatShortAccum: 731 case BuiltinType::SatAccum: 732 case BuiltinType::SatLongAccum: 733 case BuiltinType::SatUShortAccum: 734 case BuiltinType::SatUAccum: 735 case BuiltinType::SatULongAccum: 736 case BuiltinType::SatShortFract: 737 case BuiltinType::SatFract: 738 case BuiltinType::SatLongFract: 739 case BuiltinType::SatUShortFract: 740 case BuiltinType::SatUFract: 741 case BuiltinType::SatULongFract: 742 // Various types which are non-trivial to correct. 743 return false; 744 745 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 746 case BuiltinType::Id: 747 #include "clang/Basic/OpenCLImageTypes.def" 748 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \ 749 case BuiltinType::Id: 750 #include "clang/Basic/OpenCLExtensionTypes.def" 751 #define SIGNED_TYPE(Id, SingletonId) 752 #define UNSIGNED_TYPE(Id, SingletonId) 753 #define FLOATING_TYPE(Id, SingletonId) 754 #define BUILTIN_TYPE(Id, SingletonId) \ 755 case BuiltinType::Id: 756 #include "clang/AST/BuiltinTypes.def" 757 // Misc other stuff which doesn't make sense here. 758 return false; 759 760 case BuiltinType::UInt: 761 case BuiltinType::Int: 762 case BuiltinType::Float: 763 case BuiltinType::Double: 764 LM.setKind(LengthModifier::None); 765 break; 766 767 case BuiltinType::Char_U: 768 case BuiltinType::UChar: 769 case BuiltinType::Char_S: 770 case BuiltinType::SChar: 771 LM.setKind(LengthModifier::AsChar); 772 break; 773 774 case BuiltinType::Short: 775 case BuiltinType::UShort: 776 LM.setKind(LengthModifier::AsShort); 777 break; 778 779 case BuiltinType::Long: 780 case BuiltinType::ULong: 781 LM.setKind(LengthModifier::AsLong); 782 break; 783 784 case BuiltinType::LongLong: 785 case BuiltinType::ULongLong: 786 LM.setKind(LengthModifier::AsLongLong); 787 break; 788 789 case BuiltinType::LongDouble: 790 LM.setKind(LengthModifier::AsLongDouble); 791 break; 792 } 793 794 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 795 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 796 namedTypeToLengthModifier(QT, LM); 797 798 // If fixing the length modifier was enough, we might be done. 799 if (hasValidLengthModifier(Ctx.getTargetInfo())) { 800 // If we're going to offer a fix anyway, make sure the sign matches. 801 switch (CS.getKind()) { 802 case ConversionSpecifier::uArg: 803 case ConversionSpecifier::UArg: 804 if (QT->isSignedIntegerType()) 805 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); 806 break; 807 case ConversionSpecifier::dArg: 808 case ConversionSpecifier::DArg: 809 case ConversionSpecifier::iArg: 810 if (QT->isUnsignedIntegerType() && !HasPlusPrefix) 811 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); 812 break; 813 default: 814 // Other specifiers do not have signed/unsigned variants. 815 break; 816 } 817 818 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 819 if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 820 return true; 821 } 822 823 // Set conversion specifier and disable any flags which do not apply to it. 824 // Let typedefs to char fall through to int, as %c is silly for uint8_t. 825 if (!isa<TypedefType>(QT) && QT->isCharType()) { 826 CS.setKind(ConversionSpecifier::cArg); 827 LM.setKind(LengthModifier::None); 828 Precision.setHowSpecified(OptionalAmount::NotSpecified); 829 HasAlternativeForm = 0; 830 HasLeadingZeroes = 0; 831 HasPlusPrefix = 0; 832 } 833 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 834 else if (QT->isRealFloatingType()) { 835 CS.setKind(ConversionSpecifier::fArg); 836 } 837 else if (QT->isSignedIntegerType()) { 838 CS.setKind(ConversionSpecifier::dArg); 839 HasAlternativeForm = 0; 840 } 841 else if (QT->isUnsignedIntegerType()) { 842 CS.setKind(ConversionSpecifier::uArg); 843 HasAlternativeForm = 0; 844 HasPlusPrefix = 0; 845 } else { 846 llvm_unreachable("Unexpected type"); 847 } 848 849 return true; 850 } 851 852 void PrintfSpecifier::toString(raw_ostream &os) const { 853 // Whilst some features have no defined order, we are using the order 854 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 855 os << "%"; 856 857 // Positional args 858 if (usesPositionalArg()) { 859 os << getPositionalArgIndex() << "$"; 860 } 861 862 // Conversion flags 863 if (IsLeftJustified) os << "-"; 864 if (HasPlusPrefix) os << "+"; 865 if (HasSpacePrefix) os << " "; 866 if (HasAlternativeForm) os << "#"; 867 if (HasLeadingZeroes) os << "0"; 868 869 // Minimum field width 870 FieldWidth.toString(os); 871 // Precision 872 Precision.toString(os); 873 874 // Vector modifier 875 if (!VectorNumElts.isInvalid()) 876 os << 'v' << VectorNumElts.getConstantAmount(); 877 878 // Length modifier 879 os << LM.toString(); 880 // Conversion specifier 881 os << CS.toString(); 882 } 883 884 bool PrintfSpecifier::hasValidPlusPrefix() const { 885 if (!HasPlusPrefix) 886 return true; 887 888 // The plus prefix only makes sense for signed conversions 889 switch (CS.getKind()) { 890 case ConversionSpecifier::dArg: 891 case ConversionSpecifier::DArg: 892 case ConversionSpecifier::iArg: 893 case ConversionSpecifier::fArg: 894 case ConversionSpecifier::FArg: 895 case ConversionSpecifier::eArg: 896 case ConversionSpecifier::EArg: 897 case ConversionSpecifier::gArg: 898 case ConversionSpecifier::GArg: 899 case ConversionSpecifier::aArg: 900 case ConversionSpecifier::AArg: 901 case ConversionSpecifier::FreeBSDrArg: 902 case ConversionSpecifier::FreeBSDyArg: 903 return true; 904 905 default: 906 return false; 907 } 908 } 909 910 bool PrintfSpecifier::hasValidAlternativeForm() const { 911 if (!HasAlternativeForm) 912 return true; 913 914 // Alternate form flag only valid with the oxXaAeEfFgG conversions 915 switch (CS.getKind()) { 916 case ConversionSpecifier::oArg: 917 case ConversionSpecifier::OArg: 918 case ConversionSpecifier::xArg: 919 case ConversionSpecifier::XArg: 920 case ConversionSpecifier::aArg: 921 case ConversionSpecifier::AArg: 922 case ConversionSpecifier::eArg: 923 case ConversionSpecifier::EArg: 924 case ConversionSpecifier::fArg: 925 case ConversionSpecifier::FArg: 926 case ConversionSpecifier::gArg: 927 case ConversionSpecifier::GArg: 928 case ConversionSpecifier::FreeBSDrArg: 929 case ConversionSpecifier::FreeBSDyArg: 930 return true; 931 932 default: 933 return false; 934 } 935 } 936 937 bool PrintfSpecifier::hasValidLeadingZeros() const { 938 if (!HasLeadingZeroes) 939 return true; 940 941 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 942 switch (CS.getKind()) { 943 case ConversionSpecifier::dArg: 944 case ConversionSpecifier::DArg: 945 case ConversionSpecifier::iArg: 946 case ConversionSpecifier::oArg: 947 case ConversionSpecifier::OArg: 948 case ConversionSpecifier::uArg: 949 case ConversionSpecifier::UArg: 950 case ConversionSpecifier::xArg: 951 case ConversionSpecifier::XArg: 952 case ConversionSpecifier::aArg: 953 case ConversionSpecifier::AArg: 954 case ConversionSpecifier::eArg: 955 case ConversionSpecifier::EArg: 956 case ConversionSpecifier::fArg: 957 case ConversionSpecifier::FArg: 958 case ConversionSpecifier::gArg: 959 case ConversionSpecifier::GArg: 960 case ConversionSpecifier::FreeBSDrArg: 961 case ConversionSpecifier::FreeBSDyArg: 962 return true; 963 964 default: 965 return false; 966 } 967 } 968 969 bool PrintfSpecifier::hasValidSpacePrefix() const { 970 if (!HasSpacePrefix) 971 return true; 972 973 // The space prefix only makes sense for signed conversions 974 switch (CS.getKind()) { 975 case ConversionSpecifier::dArg: 976 case ConversionSpecifier::DArg: 977 case ConversionSpecifier::iArg: 978 case ConversionSpecifier::fArg: 979 case ConversionSpecifier::FArg: 980 case ConversionSpecifier::eArg: 981 case ConversionSpecifier::EArg: 982 case ConversionSpecifier::gArg: 983 case ConversionSpecifier::GArg: 984 case ConversionSpecifier::aArg: 985 case ConversionSpecifier::AArg: 986 case ConversionSpecifier::FreeBSDrArg: 987 case ConversionSpecifier::FreeBSDyArg: 988 return true; 989 990 default: 991 return false; 992 } 993 } 994 995 bool PrintfSpecifier::hasValidLeftJustified() const { 996 if (!IsLeftJustified) 997 return true; 998 999 // The left justified flag is valid for all conversions except n 1000 switch (CS.getKind()) { 1001 case ConversionSpecifier::nArg: 1002 return false; 1003 1004 default: 1005 return true; 1006 } 1007 } 1008 1009 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 1010 if (!HasThousandsGrouping) 1011 return true; 1012 1013 switch (CS.getKind()) { 1014 case ConversionSpecifier::dArg: 1015 case ConversionSpecifier::DArg: 1016 case ConversionSpecifier::iArg: 1017 case ConversionSpecifier::uArg: 1018 case ConversionSpecifier::UArg: 1019 case ConversionSpecifier::fArg: 1020 case ConversionSpecifier::FArg: 1021 case ConversionSpecifier::gArg: 1022 case ConversionSpecifier::GArg: 1023 return true; 1024 default: 1025 return false; 1026 } 1027 } 1028 1029 bool PrintfSpecifier::hasValidPrecision() const { 1030 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 1031 return true; 1032 1033 // Precision is only valid with the diouxXaAeEfFgGsP conversions 1034 switch (CS.getKind()) { 1035 case ConversionSpecifier::dArg: 1036 case ConversionSpecifier::DArg: 1037 case ConversionSpecifier::iArg: 1038 case ConversionSpecifier::oArg: 1039 case ConversionSpecifier::OArg: 1040 case ConversionSpecifier::uArg: 1041 case ConversionSpecifier::UArg: 1042 case ConversionSpecifier::xArg: 1043 case ConversionSpecifier::XArg: 1044 case ConversionSpecifier::aArg: 1045 case ConversionSpecifier::AArg: 1046 case ConversionSpecifier::eArg: 1047 case ConversionSpecifier::EArg: 1048 case ConversionSpecifier::fArg: 1049 case ConversionSpecifier::FArg: 1050 case ConversionSpecifier::gArg: 1051 case ConversionSpecifier::GArg: 1052 case ConversionSpecifier::sArg: 1053 case ConversionSpecifier::FreeBSDrArg: 1054 case ConversionSpecifier::FreeBSDyArg: 1055 case ConversionSpecifier::PArg: 1056 return true; 1057 1058 default: 1059 return false; 1060 } 1061 } 1062 bool PrintfSpecifier::hasValidFieldWidth() const { 1063 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 1064 return true; 1065 1066 // The field width is valid for all conversions except n 1067 switch (CS.getKind()) { 1068 case ConversionSpecifier::nArg: 1069 return false; 1070 1071 default: 1072 return true; 1073 } 1074 } 1075