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