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