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