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
ParsePrecision(FormatStringHandler & H,PrintfSpecifier & FS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)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
ParseObjCFlags(FormatStringHandler & H,PrintfSpecifier & FS,const char * FlagBeg,const char * E,bool Warn)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
ParsePrintfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target,bool Warn,bool isFreeBSDKPrintf)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.
321 if (!LO.OpenCL)
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
ParsePrintfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target,bool isFreeBSDKPrintf)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()))
432 return true;
433 }
434 assert(I == E && "Format string not exhausted");
435 return false;
436 }
437
ParseFormatStringHasSArg(const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)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
parseFormatStringHasFormattingSpecifiers(const char * Begin,const char * End,const LangOptions & LO,const TargetInfo & Target)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
getScalarArgType(ASTContext & Ctx,bool IsObjCLiteral) const488 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
getArgType(ASTContext & Ctx,bool IsObjCLiteral) const667 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
fixType(QualType QT,const LangOptions & LangOpt,ASTContext & Ctx,bool IsObjCLiteral)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 = 0;
715 HasLeadingZeroes = 0;
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::ShortAccum:
759 case BuiltinType::Accum:
760 case BuiltinType::LongAccum:
761 case BuiltinType::UShortAccum:
762 case BuiltinType::UAccum:
763 case BuiltinType::ULongAccum:
764 case BuiltinType::ShortFract:
765 case BuiltinType::Fract:
766 case BuiltinType::LongFract:
767 case BuiltinType::UShortFract:
768 case BuiltinType::UFract:
769 case BuiltinType::ULongFract:
770 case BuiltinType::SatShortAccum:
771 case BuiltinType::SatAccum:
772 case BuiltinType::SatLongAccum:
773 case BuiltinType::SatUShortAccum:
774 case BuiltinType::SatUAccum:
775 case BuiltinType::SatULongAccum:
776 case BuiltinType::SatShortFract:
777 case BuiltinType::SatFract:
778 case BuiltinType::SatLongFract:
779 case BuiltinType::SatUShortFract:
780 case BuiltinType::SatUFract:
781 case BuiltinType::SatULongFract:
782 // Various types which are non-trivial to correct.
783 return false;
784
785 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
786 case BuiltinType::Id:
787 #include "clang/Basic/OpenCLImageTypes.def"
788 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
789 case BuiltinType::Id:
790 #include "clang/Basic/OpenCLExtensionTypes.def"
791 #define SVE_TYPE(Name, Id, SingletonId) \
792 case BuiltinType::Id:
793 #include "clang/Basic/AArch64SVEACLETypes.def"
794 #define PPC_MMA_VECTOR_TYPE(Name, Id, Size) \
795 case BuiltinType::Id:
796 #include "clang/Basic/PPCTypes.def"
797 #define SIGNED_TYPE(Id, SingletonId)
798 #define UNSIGNED_TYPE(Id, SingletonId)
799 #define FLOATING_TYPE(Id, SingletonId)
800 #define BUILTIN_TYPE(Id, SingletonId) \
801 case BuiltinType::Id:
802 #include "clang/AST/BuiltinTypes.def"
803 // Misc other stuff which doesn't make sense here.
804 return false;
805
806 case BuiltinType::UInt:
807 case BuiltinType::Int:
808 case BuiltinType::Float:
809 LM.setKind(VectorNumElts.isInvalid() ?
810 LengthModifier::None : LengthModifier::AsShortLong);
811 break;
812 case BuiltinType::Double:
813 LM.setKind(VectorNumElts.isInvalid() ?
814 LengthModifier::None : LengthModifier::AsLong);
815 break;
816 case BuiltinType::Char_U:
817 case BuiltinType::UChar:
818 case BuiltinType::Char_S:
819 case BuiltinType::SChar:
820 LM.setKind(LengthModifier::AsChar);
821 break;
822
823 case BuiltinType::Short:
824 case BuiltinType::UShort:
825 LM.setKind(LengthModifier::AsShort);
826 break;
827
828 case BuiltinType::Long:
829 case BuiltinType::ULong:
830 LM.setKind(LengthModifier::AsLong);
831 break;
832
833 case BuiltinType::LongLong:
834 case BuiltinType::ULongLong:
835 LM.setKind(LengthModifier::AsLongLong);
836 break;
837
838 case BuiltinType::LongDouble:
839 LM.setKind(LengthModifier::AsLongDouble);
840 break;
841 }
842
843 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
844 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
845 namedTypeToLengthModifier(QT, LM);
846
847 // If fixing the length modifier was enough, we might be done.
848 if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
849 // If we're going to offer a fix anyway, make sure the sign matches.
850 switch (CS.getKind()) {
851 case ConversionSpecifier::uArg:
852 case ConversionSpecifier::UArg:
853 if (QT->isSignedIntegerType())
854 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
855 break;
856 case ConversionSpecifier::dArg:
857 case ConversionSpecifier::DArg:
858 case ConversionSpecifier::iArg:
859 if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
860 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
861 break;
862 default:
863 // Other specifiers do not have signed/unsigned variants.
864 break;
865 }
866
867 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
868 if (ATR.isValid() && ATR.matchesType(Ctx, QT))
869 return true;
870 }
871
872 // Set conversion specifier and disable any flags which do not apply to it.
873 // Let typedefs to char fall through to int, as %c is silly for uint8_t.
874 if (!isa<TypedefType>(QT) && QT->isCharType()) {
875 CS.setKind(ConversionSpecifier::cArg);
876 LM.setKind(LengthModifier::None);
877 Precision.setHowSpecified(OptionalAmount::NotSpecified);
878 HasAlternativeForm = 0;
879 HasLeadingZeroes = 0;
880 HasPlusPrefix = 0;
881 }
882 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
883 else if (QT->isRealFloatingType()) {
884 CS.setKind(ConversionSpecifier::fArg);
885 }
886 else if (QT->isSignedIntegerType()) {
887 CS.setKind(ConversionSpecifier::dArg);
888 HasAlternativeForm = 0;
889 }
890 else if (QT->isUnsignedIntegerType()) {
891 CS.setKind(ConversionSpecifier::uArg);
892 HasAlternativeForm = 0;
893 HasPlusPrefix = 0;
894 } else {
895 llvm_unreachable("Unexpected type");
896 }
897
898 return true;
899 }
900
toString(raw_ostream & os) const901 void PrintfSpecifier::toString(raw_ostream &os) const {
902 // Whilst some features have no defined order, we are using the order
903 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
904 os << "%";
905
906 // Positional args
907 if (usesPositionalArg()) {
908 os << getPositionalArgIndex() << "$";
909 }
910
911 // Conversion flags
912 if (IsLeftJustified) os << "-";
913 if (HasPlusPrefix) os << "+";
914 if (HasSpacePrefix) os << " ";
915 if (HasAlternativeForm) os << "#";
916 if (HasLeadingZeroes) os << "0";
917
918 // Minimum field width
919 FieldWidth.toString(os);
920 // Precision
921 Precision.toString(os);
922
923 // Vector modifier
924 if (!VectorNumElts.isInvalid())
925 os << 'v' << VectorNumElts.getConstantAmount();
926
927 // Length modifier
928 os << LM.toString();
929 // Conversion specifier
930 os << CS.toString();
931 }
932
hasValidPlusPrefix() const933 bool PrintfSpecifier::hasValidPlusPrefix() const {
934 if (!HasPlusPrefix)
935 return true;
936
937 // The plus prefix only makes sense for signed conversions
938 switch (CS.getKind()) {
939 case ConversionSpecifier::dArg:
940 case ConversionSpecifier::DArg:
941 case ConversionSpecifier::iArg:
942 case ConversionSpecifier::fArg:
943 case ConversionSpecifier::FArg:
944 case ConversionSpecifier::eArg:
945 case ConversionSpecifier::EArg:
946 case ConversionSpecifier::gArg:
947 case ConversionSpecifier::GArg:
948 case ConversionSpecifier::aArg:
949 case ConversionSpecifier::AArg:
950 case ConversionSpecifier::FreeBSDrArg:
951 case ConversionSpecifier::FreeBSDyArg:
952 return true;
953
954 default:
955 return false;
956 }
957 }
958
hasValidAlternativeForm() const959 bool PrintfSpecifier::hasValidAlternativeForm() const {
960 if (!HasAlternativeForm)
961 return true;
962
963 // Alternate form flag only valid with the oxXaAeEfFgG conversions
964 switch (CS.getKind()) {
965 case ConversionSpecifier::oArg:
966 case ConversionSpecifier::OArg:
967 case ConversionSpecifier::xArg:
968 case ConversionSpecifier::XArg:
969 case ConversionSpecifier::aArg:
970 case ConversionSpecifier::AArg:
971 case ConversionSpecifier::eArg:
972 case ConversionSpecifier::EArg:
973 case ConversionSpecifier::fArg:
974 case ConversionSpecifier::FArg:
975 case ConversionSpecifier::gArg:
976 case ConversionSpecifier::GArg:
977 case ConversionSpecifier::FreeBSDrArg:
978 case ConversionSpecifier::FreeBSDyArg:
979 return true;
980
981 default:
982 return false;
983 }
984 }
985
hasValidLeadingZeros() const986 bool PrintfSpecifier::hasValidLeadingZeros() const {
987 if (!HasLeadingZeroes)
988 return true;
989
990 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
991 switch (CS.getKind()) {
992 case ConversionSpecifier::dArg:
993 case ConversionSpecifier::DArg:
994 case ConversionSpecifier::iArg:
995 case ConversionSpecifier::oArg:
996 case ConversionSpecifier::OArg:
997 case ConversionSpecifier::uArg:
998 case ConversionSpecifier::UArg:
999 case ConversionSpecifier::xArg:
1000 case ConversionSpecifier::XArg:
1001 case ConversionSpecifier::aArg:
1002 case ConversionSpecifier::AArg:
1003 case ConversionSpecifier::eArg:
1004 case ConversionSpecifier::EArg:
1005 case ConversionSpecifier::fArg:
1006 case ConversionSpecifier::FArg:
1007 case ConversionSpecifier::gArg:
1008 case ConversionSpecifier::GArg:
1009 case ConversionSpecifier::FreeBSDrArg:
1010 case ConversionSpecifier::FreeBSDyArg:
1011 return true;
1012
1013 default:
1014 return false;
1015 }
1016 }
1017
hasValidSpacePrefix() const1018 bool PrintfSpecifier::hasValidSpacePrefix() const {
1019 if (!HasSpacePrefix)
1020 return true;
1021
1022 // The space prefix only makes sense for signed conversions
1023 switch (CS.getKind()) {
1024 case ConversionSpecifier::dArg:
1025 case ConversionSpecifier::DArg:
1026 case ConversionSpecifier::iArg:
1027 case ConversionSpecifier::fArg:
1028 case ConversionSpecifier::FArg:
1029 case ConversionSpecifier::eArg:
1030 case ConversionSpecifier::EArg:
1031 case ConversionSpecifier::gArg:
1032 case ConversionSpecifier::GArg:
1033 case ConversionSpecifier::aArg:
1034 case ConversionSpecifier::AArg:
1035 case ConversionSpecifier::FreeBSDrArg:
1036 case ConversionSpecifier::FreeBSDyArg:
1037 return true;
1038
1039 default:
1040 return false;
1041 }
1042 }
1043
hasValidLeftJustified() const1044 bool PrintfSpecifier::hasValidLeftJustified() const {
1045 if (!IsLeftJustified)
1046 return true;
1047
1048 // The left justified flag is valid for all conversions except n
1049 switch (CS.getKind()) {
1050 case ConversionSpecifier::nArg:
1051 return false;
1052
1053 default:
1054 return true;
1055 }
1056 }
1057
hasValidThousandsGroupingPrefix() const1058 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1059 if (!HasThousandsGrouping)
1060 return true;
1061
1062 switch (CS.getKind()) {
1063 case ConversionSpecifier::dArg:
1064 case ConversionSpecifier::DArg:
1065 case ConversionSpecifier::iArg:
1066 case ConversionSpecifier::uArg:
1067 case ConversionSpecifier::UArg:
1068 case ConversionSpecifier::fArg:
1069 case ConversionSpecifier::FArg:
1070 case ConversionSpecifier::gArg:
1071 case ConversionSpecifier::GArg:
1072 return true;
1073 default:
1074 return false;
1075 }
1076 }
1077
hasValidPrecision() const1078 bool PrintfSpecifier::hasValidPrecision() const {
1079 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1080 return true;
1081
1082 // Precision is only valid with the diouxXaAeEfFgGsP conversions
1083 switch (CS.getKind()) {
1084 case ConversionSpecifier::dArg:
1085 case ConversionSpecifier::DArg:
1086 case ConversionSpecifier::iArg:
1087 case ConversionSpecifier::oArg:
1088 case ConversionSpecifier::OArg:
1089 case ConversionSpecifier::uArg:
1090 case ConversionSpecifier::UArg:
1091 case ConversionSpecifier::xArg:
1092 case ConversionSpecifier::XArg:
1093 case ConversionSpecifier::aArg:
1094 case ConversionSpecifier::AArg:
1095 case ConversionSpecifier::eArg:
1096 case ConversionSpecifier::EArg:
1097 case ConversionSpecifier::fArg:
1098 case ConversionSpecifier::FArg:
1099 case ConversionSpecifier::gArg:
1100 case ConversionSpecifier::GArg:
1101 case ConversionSpecifier::sArg:
1102 case ConversionSpecifier::FreeBSDrArg:
1103 case ConversionSpecifier::FreeBSDyArg:
1104 case ConversionSpecifier::PArg:
1105 return true;
1106
1107 default:
1108 return false;
1109 }
1110 }
hasValidFieldWidth() const1111 bool PrintfSpecifier::hasValidFieldWidth() const {
1112 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1113 return true;
1114
1115 // The field width is valid for all conversions except n
1116 switch (CS.getKind()) {
1117 case ConversionSpecifier::nArg:
1118 return false;
1119
1120 default:
1121 return true;
1122 }
1123 }
1124