1*b5893f02SDimitry Andric //= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric //                     The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric //
10*b5893f02SDimitry Andric // Handling of format string in scanf and friends.  The structure of format
11*b5893f02SDimitry Andric // strings for fscanf() are described in C99 7.19.6.2.
12*b5893f02SDimitry Andric //
13*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
14*b5893f02SDimitry Andric 
15*b5893f02SDimitry Andric #include "clang/AST/FormatString.h"
16*b5893f02SDimitry Andric #include "FormatStringParsing.h"
17*b5893f02SDimitry Andric #include "clang/Basic/TargetInfo.h"
18*b5893f02SDimitry Andric 
19*b5893f02SDimitry Andric using clang::analyze_format_string::ArgType;
20*b5893f02SDimitry Andric using clang::analyze_format_string::FormatStringHandler;
21*b5893f02SDimitry Andric using clang::analyze_format_string::LengthModifier;
22*b5893f02SDimitry Andric using clang::analyze_format_string::OptionalAmount;
23*b5893f02SDimitry Andric using clang::analyze_format_string::ConversionSpecifier;
24*b5893f02SDimitry Andric using clang::analyze_scanf::ScanfConversionSpecifier;
25*b5893f02SDimitry Andric using clang::analyze_scanf::ScanfSpecifier;
26*b5893f02SDimitry Andric using clang::UpdateOnReturn;
27*b5893f02SDimitry Andric using namespace clang;
28*b5893f02SDimitry Andric 
29*b5893f02SDimitry Andric typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
30*b5893f02SDimitry Andric         ScanfSpecifierResult;
31*b5893f02SDimitry Andric 
ParseScanList(FormatStringHandler & H,ScanfConversionSpecifier & CS,const char * & Beg,const char * E)32*b5893f02SDimitry Andric static bool ParseScanList(FormatStringHandler &H,
33*b5893f02SDimitry Andric                           ScanfConversionSpecifier &CS,
34*b5893f02SDimitry Andric                           const char *&Beg, const char *E) {
35*b5893f02SDimitry Andric   const char *I = Beg;
36*b5893f02SDimitry Andric   const char *start = I - 1;
37*b5893f02SDimitry Andric   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
38*b5893f02SDimitry Andric 
39*b5893f02SDimitry Andric   // No more characters?
40*b5893f02SDimitry Andric   if (I == E) {
41*b5893f02SDimitry Andric     H.HandleIncompleteScanList(start, I);
42*b5893f02SDimitry Andric     return true;
43*b5893f02SDimitry Andric   }
44*b5893f02SDimitry Andric 
45*b5893f02SDimitry Andric   // Special case: ']' is the first character.
46*b5893f02SDimitry Andric   if (*I == ']') {
47*b5893f02SDimitry Andric     if (++I == E) {
48*b5893f02SDimitry Andric       H.HandleIncompleteScanList(start, I - 1);
49*b5893f02SDimitry Andric       return true;
50*b5893f02SDimitry Andric     }
51*b5893f02SDimitry Andric   }
52*b5893f02SDimitry Andric 
53*b5893f02SDimitry Andric   // Special case: "^]" are the first characters.
54*b5893f02SDimitry Andric   if (I + 1 != E && I[0] == '^' && I[1] == ']') {
55*b5893f02SDimitry Andric     I += 2;
56*b5893f02SDimitry Andric     if (I == E) {
57*b5893f02SDimitry Andric       H.HandleIncompleteScanList(start, I - 1);
58*b5893f02SDimitry Andric       return true;
59*b5893f02SDimitry Andric     }
60*b5893f02SDimitry Andric   }
61*b5893f02SDimitry Andric 
62*b5893f02SDimitry Andric   // Look for a ']' character which denotes the end of the scan list.
63*b5893f02SDimitry Andric   while (*I != ']') {
64*b5893f02SDimitry Andric     if (++I == E) {
65*b5893f02SDimitry Andric       H.HandleIncompleteScanList(start, I - 1);
66*b5893f02SDimitry Andric       return true;
67*b5893f02SDimitry Andric     }
68*b5893f02SDimitry Andric   }
69*b5893f02SDimitry Andric 
70*b5893f02SDimitry Andric   CS.setEndScanList(I);
71*b5893f02SDimitry Andric   return false;
72*b5893f02SDimitry Andric }
73*b5893f02SDimitry Andric 
74*b5893f02SDimitry Andric // FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
75*b5893f02SDimitry Andric // We can possibly refactor.
ParseScanfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target)76*b5893f02SDimitry Andric static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
77*b5893f02SDimitry Andric                                                 const char *&Beg,
78*b5893f02SDimitry Andric                                                 const char *E,
79*b5893f02SDimitry Andric                                                 unsigned &argIndex,
80*b5893f02SDimitry Andric                                                 const LangOptions &LO,
81*b5893f02SDimitry Andric                                                 const TargetInfo &Target) {
82*b5893f02SDimitry Andric   using namespace clang::analyze_format_string;
83*b5893f02SDimitry Andric   using namespace clang::analyze_scanf;
84*b5893f02SDimitry Andric   const char *I = Beg;
85*b5893f02SDimitry Andric   const char *Start = nullptr;
86*b5893f02SDimitry Andric   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
87*b5893f02SDimitry Andric 
88*b5893f02SDimitry Andric     // Look for a '%' character that indicates the start of a format specifier.
89*b5893f02SDimitry Andric   for ( ; I != E ; ++I) {
90*b5893f02SDimitry Andric     char c = *I;
91*b5893f02SDimitry Andric     if (c == '\0') {
92*b5893f02SDimitry Andric         // Detect spurious null characters, which are likely errors.
93*b5893f02SDimitry Andric       H.HandleNullChar(I);
94*b5893f02SDimitry Andric       return true;
95*b5893f02SDimitry Andric     }
96*b5893f02SDimitry Andric     if (c == '%') {
97*b5893f02SDimitry Andric       Start = I++;  // Record the start of the format specifier.
98*b5893f02SDimitry Andric       break;
99*b5893f02SDimitry Andric     }
100*b5893f02SDimitry Andric   }
101*b5893f02SDimitry Andric 
102*b5893f02SDimitry Andric     // No format specifier found?
103*b5893f02SDimitry Andric   if (!Start)
104*b5893f02SDimitry Andric     return false;
105*b5893f02SDimitry Andric 
106*b5893f02SDimitry Andric   if (I == E) {
107*b5893f02SDimitry Andric       // No more characters left?
108*b5893f02SDimitry Andric     H.HandleIncompleteSpecifier(Start, E - Start);
109*b5893f02SDimitry Andric     return true;
110*b5893f02SDimitry Andric   }
111*b5893f02SDimitry Andric 
112*b5893f02SDimitry Andric   ScanfSpecifier FS;
113*b5893f02SDimitry Andric   if (ParseArgPosition(H, FS, Start, I, E))
114*b5893f02SDimitry Andric     return true;
115*b5893f02SDimitry Andric 
116*b5893f02SDimitry Andric   if (I == E) {
117*b5893f02SDimitry Andric       // No more characters left?
118*b5893f02SDimitry Andric     H.HandleIncompleteSpecifier(Start, E - Start);
119*b5893f02SDimitry Andric     return true;
120*b5893f02SDimitry Andric   }
121*b5893f02SDimitry Andric 
122*b5893f02SDimitry Andric   // Look for '*' flag if it is present.
123*b5893f02SDimitry Andric   if (*I == '*') {
124*b5893f02SDimitry Andric     FS.setSuppressAssignment(I);
125*b5893f02SDimitry Andric     if (++I == E) {
126*b5893f02SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
127*b5893f02SDimitry Andric       return true;
128*b5893f02SDimitry Andric     }
129*b5893f02SDimitry Andric   }
130*b5893f02SDimitry Andric 
131*b5893f02SDimitry Andric   // Look for the field width (if any).  Unlike printf, this is either
132*b5893f02SDimitry Andric   // a fixed integer or isn't present.
133*b5893f02SDimitry Andric   const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
134*b5893f02SDimitry Andric   if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
135*b5893f02SDimitry Andric     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
136*b5893f02SDimitry Andric     FS.setFieldWidth(Amt);
137*b5893f02SDimitry Andric 
138*b5893f02SDimitry Andric     if (I == E) {
139*b5893f02SDimitry Andric       // No more characters left?
140*b5893f02SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
141*b5893f02SDimitry Andric       return true;
142*b5893f02SDimitry Andric     }
143*b5893f02SDimitry Andric   }
144*b5893f02SDimitry Andric 
145*b5893f02SDimitry Andric   // Look for the length modifier.
146*b5893f02SDimitry Andric   if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
147*b5893f02SDimitry Andric       // No more characters left?
148*b5893f02SDimitry Andric     H.HandleIncompleteSpecifier(Start, E - Start);
149*b5893f02SDimitry Andric     return true;
150*b5893f02SDimitry Andric   }
151*b5893f02SDimitry Andric 
152*b5893f02SDimitry Andric   // Detect spurious null characters, which are likely errors.
153*b5893f02SDimitry Andric   if (*I == '\0') {
154*b5893f02SDimitry Andric     H.HandleNullChar(I);
155*b5893f02SDimitry Andric     return true;
156*b5893f02SDimitry Andric   }
157*b5893f02SDimitry Andric 
158*b5893f02SDimitry Andric   // Finally, look for the conversion specifier.
159*b5893f02SDimitry Andric   const char *conversionPosition = I++;
160*b5893f02SDimitry Andric   ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
161*b5893f02SDimitry Andric   switch (*conversionPosition) {
162*b5893f02SDimitry Andric     default:
163*b5893f02SDimitry Andric       break;
164*b5893f02SDimitry Andric     case '%': k = ConversionSpecifier::PercentArg;   break;
165*b5893f02SDimitry Andric     case 'A': k = ConversionSpecifier::AArg; break;
166*b5893f02SDimitry Andric     case 'E': k = ConversionSpecifier::EArg; break;
167*b5893f02SDimitry Andric     case 'F': k = ConversionSpecifier::FArg; break;
168*b5893f02SDimitry Andric     case 'G': k = ConversionSpecifier::GArg; break;
169*b5893f02SDimitry Andric     case 'X': k = ConversionSpecifier::XArg; break;
170*b5893f02SDimitry Andric     case 'a': k = ConversionSpecifier::aArg; break;
171*b5893f02SDimitry Andric     case 'd': k = ConversionSpecifier::dArg; break;
172*b5893f02SDimitry Andric     case 'e': k = ConversionSpecifier::eArg; break;
173*b5893f02SDimitry Andric     case 'f': k = ConversionSpecifier::fArg; break;
174*b5893f02SDimitry Andric     case 'g': k = ConversionSpecifier::gArg; break;
175*b5893f02SDimitry Andric     case 'i': k = ConversionSpecifier::iArg; break;
176*b5893f02SDimitry Andric     case 'n': k = ConversionSpecifier::nArg; break;
177*b5893f02SDimitry Andric     case 'c': k = ConversionSpecifier::cArg; break;
178*b5893f02SDimitry Andric     case 'C': k = ConversionSpecifier::CArg; break;
179*b5893f02SDimitry Andric     case 'S': k = ConversionSpecifier::SArg; break;
180*b5893f02SDimitry Andric     case '[': k = ConversionSpecifier::ScanListArg; break;
181*b5893f02SDimitry Andric     case 'u': k = ConversionSpecifier::uArg; break;
182*b5893f02SDimitry Andric     case 'x': k = ConversionSpecifier::xArg; break;
183*b5893f02SDimitry Andric     case 'o': k = ConversionSpecifier::oArg; break;
184*b5893f02SDimitry Andric     case 's': k = ConversionSpecifier::sArg; break;
185*b5893f02SDimitry Andric     case 'p': k = ConversionSpecifier::pArg; break;
186*b5893f02SDimitry Andric     // Apple extensions
187*b5893f02SDimitry Andric       // Apple-specific
188*b5893f02SDimitry Andric     case 'D':
189*b5893f02SDimitry Andric       if (Target.getTriple().isOSDarwin())
190*b5893f02SDimitry Andric         k = ConversionSpecifier::DArg;
191*b5893f02SDimitry Andric       break;
192*b5893f02SDimitry Andric     case 'O':
193*b5893f02SDimitry Andric       if (Target.getTriple().isOSDarwin())
194*b5893f02SDimitry Andric         k = ConversionSpecifier::OArg;
195*b5893f02SDimitry Andric       break;
196*b5893f02SDimitry Andric     case 'U':
197*b5893f02SDimitry Andric       if (Target.getTriple().isOSDarwin())
198*b5893f02SDimitry Andric         k = ConversionSpecifier::UArg;
199*b5893f02SDimitry Andric       break;
200*b5893f02SDimitry Andric   }
201*b5893f02SDimitry Andric   ScanfConversionSpecifier CS(conversionPosition, k);
202*b5893f02SDimitry Andric   if (k == ScanfConversionSpecifier::ScanListArg) {
203*b5893f02SDimitry Andric     if (ParseScanList(H, CS, I, E))
204*b5893f02SDimitry Andric       return true;
205*b5893f02SDimitry Andric   }
206*b5893f02SDimitry Andric   FS.setConversionSpecifier(CS);
207*b5893f02SDimitry Andric   if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
208*b5893f02SDimitry Andric       && !FS.usesPositionalArg())
209*b5893f02SDimitry Andric     FS.setArgIndex(argIndex++);
210*b5893f02SDimitry Andric 
211*b5893f02SDimitry Andric   // FIXME: '%' and '*' doesn't make sense.  Issue a warning.
212*b5893f02SDimitry Andric   // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
213*b5893f02SDimitry Andric 
214*b5893f02SDimitry Andric   if (k == ScanfConversionSpecifier::InvalidSpecifier) {
215*b5893f02SDimitry Andric     unsigned Len = I - Beg;
216*b5893f02SDimitry Andric     if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
217*b5893f02SDimitry Andric       CS.setEndScanList(Beg + Len);
218*b5893f02SDimitry Andric       FS.setConversionSpecifier(CS);
219*b5893f02SDimitry Andric     }
220*b5893f02SDimitry Andric     // Assume the conversion takes one argument.
221*b5893f02SDimitry Andric     return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
222*b5893f02SDimitry Andric   }
223*b5893f02SDimitry Andric   return ScanfSpecifierResult(Start, FS);
224*b5893f02SDimitry Andric }
225*b5893f02SDimitry Andric 
getArgType(ASTContext & Ctx) const226*b5893f02SDimitry Andric ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
227*b5893f02SDimitry Andric   const ScanfConversionSpecifier &CS = getConversionSpecifier();
228*b5893f02SDimitry Andric 
229*b5893f02SDimitry Andric   if (!CS.consumesDataArgument())
230*b5893f02SDimitry Andric     return ArgType::Invalid();
231*b5893f02SDimitry Andric 
232*b5893f02SDimitry Andric   switch(CS.getKind()) {
233*b5893f02SDimitry Andric     // Signed int.
234*b5893f02SDimitry Andric     case ConversionSpecifier::dArg:
235*b5893f02SDimitry Andric     case ConversionSpecifier::DArg:
236*b5893f02SDimitry Andric     case ConversionSpecifier::iArg:
237*b5893f02SDimitry Andric       switch (LM.getKind()) {
238*b5893f02SDimitry Andric         case LengthModifier::None:
239*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.IntTy);
240*b5893f02SDimitry Andric         case LengthModifier::AsChar:
241*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType::AnyCharTy);
242*b5893f02SDimitry Andric         case LengthModifier::AsShort:
243*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.ShortTy);
244*b5893f02SDimitry Andric         case LengthModifier::AsLong:
245*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongTy);
246*b5893f02SDimitry Andric         case LengthModifier::AsLongLong:
247*b5893f02SDimitry Andric         case LengthModifier::AsQuad:
248*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongLongTy);
249*b5893f02SDimitry Andric         case LengthModifier::AsInt64:
250*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
251*b5893f02SDimitry Andric         case LengthModifier::AsIntMax:
252*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
253*b5893f02SDimitry Andric         case LengthModifier::AsSizeT:
254*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
255*b5893f02SDimitry Andric         case LengthModifier::AsPtrDiff:
256*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
257*b5893f02SDimitry Andric         case LengthModifier::AsLongDouble:
258*b5893f02SDimitry Andric           // GNU extension.
259*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongLongTy);
260*b5893f02SDimitry Andric         case LengthModifier::AsAllocate:
261*b5893f02SDimitry Andric         case LengthModifier::AsMAllocate:
262*b5893f02SDimitry Andric         case LengthModifier::AsInt32:
263*b5893f02SDimitry Andric         case LengthModifier::AsInt3264:
264*b5893f02SDimitry Andric         case LengthModifier::AsWide:
265*b5893f02SDimitry Andric           return ArgType::Invalid();
266*b5893f02SDimitry Andric       }
267*b5893f02SDimitry Andric       llvm_unreachable("Unsupported LenghtModifier Type");
268*b5893f02SDimitry Andric 
269*b5893f02SDimitry Andric     // Unsigned int.
270*b5893f02SDimitry Andric     case ConversionSpecifier::oArg:
271*b5893f02SDimitry Andric     case ConversionSpecifier::OArg:
272*b5893f02SDimitry Andric     case ConversionSpecifier::uArg:
273*b5893f02SDimitry Andric     case ConversionSpecifier::UArg:
274*b5893f02SDimitry Andric     case ConversionSpecifier::xArg:
275*b5893f02SDimitry Andric     case ConversionSpecifier::XArg:
276*b5893f02SDimitry Andric       switch (LM.getKind()) {
277*b5893f02SDimitry Andric         case LengthModifier::None:
278*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedIntTy);
279*b5893f02SDimitry Andric         case LengthModifier::AsChar:
280*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedCharTy);
281*b5893f02SDimitry Andric         case LengthModifier::AsShort:
282*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedShortTy);
283*b5893f02SDimitry Andric         case LengthModifier::AsLong:
284*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedLongTy);
285*b5893f02SDimitry Andric         case LengthModifier::AsLongLong:
286*b5893f02SDimitry Andric         case LengthModifier::AsQuad:
287*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
288*b5893f02SDimitry Andric         case LengthModifier::AsInt64:
289*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
290*b5893f02SDimitry Andric         case LengthModifier::AsIntMax:
291*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
292*b5893f02SDimitry Andric         case LengthModifier::AsSizeT:
293*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
294*b5893f02SDimitry Andric         case LengthModifier::AsPtrDiff:
295*b5893f02SDimitry Andric           return ArgType::PtrTo(
296*b5893f02SDimitry Andric               ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
297*b5893f02SDimitry Andric         case LengthModifier::AsLongDouble:
298*b5893f02SDimitry Andric           // GNU extension.
299*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
300*b5893f02SDimitry Andric         case LengthModifier::AsAllocate:
301*b5893f02SDimitry Andric         case LengthModifier::AsMAllocate:
302*b5893f02SDimitry Andric         case LengthModifier::AsInt32:
303*b5893f02SDimitry Andric         case LengthModifier::AsInt3264:
304*b5893f02SDimitry Andric         case LengthModifier::AsWide:
305*b5893f02SDimitry Andric           return ArgType::Invalid();
306*b5893f02SDimitry Andric       }
307*b5893f02SDimitry Andric       llvm_unreachable("Unsupported LenghtModifier Type");
308*b5893f02SDimitry Andric 
309*b5893f02SDimitry Andric     // Float.
310*b5893f02SDimitry Andric     case ConversionSpecifier::aArg:
311*b5893f02SDimitry Andric     case ConversionSpecifier::AArg:
312*b5893f02SDimitry Andric     case ConversionSpecifier::eArg:
313*b5893f02SDimitry Andric     case ConversionSpecifier::EArg:
314*b5893f02SDimitry Andric     case ConversionSpecifier::fArg:
315*b5893f02SDimitry Andric     case ConversionSpecifier::FArg:
316*b5893f02SDimitry Andric     case ConversionSpecifier::gArg:
317*b5893f02SDimitry Andric     case ConversionSpecifier::GArg:
318*b5893f02SDimitry Andric       switch (LM.getKind()) {
319*b5893f02SDimitry Andric         case LengthModifier::None:
320*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.FloatTy);
321*b5893f02SDimitry Andric         case LengthModifier::AsLong:
322*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.DoubleTy);
323*b5893f02SDimitry Andric         case LengthModifier::AsLongDouble:
324*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongDoubleTy);
325*b5893f02SDimitry Andric         default:
326*b5893f02SDimitry Andric           return ArgType::Invalid();
327*b5893f02SDimitry Andric       }
328*b5893f02SDimitry Andric 
329*b5893f02SDimitry Andric     // Char, string and scanlist.
330*b5893f02SDimitry Andric     case ConversionSpecifier::cArg:
331*b5893f02SDimitry Andric     case ConversionSpecifier::sArg:
332*b5893f02SDimitry Andric     case ConversionSpecifier::ScanListArg:
333*b5893f02SDimitry Andric       switch (LM.getKind()) {
334*b5893f02SDimitry Andric         case LengthModifier::None:
335*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType::AnyCharTy);
336*b5893f02SDimitry Andric         case LengthModifier::AsLong:
337*b5893f02SDimitry Andric         case LengthModifier::AsWide:
338*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
339*b5893f02SDimitry Andric         case LengthModifier::AsAllocate:
340*b5893f02SDimitry Andric         case LengthModifier::AsMAllocate:
341*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType::CStrTy);
342*b5893f02SDimitry Andric         case LengthModifier::AsShort:
343*b5893f02SDimitry Andric           if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
344*b5893f02SDimitry Andric             return ArgType::PtrTo(ArgType::AnyCharTy);
345*b5893f02SDimitry Andric           LLVM_FALLTHROUGH;
346*b5893f02SDimitry Andric         default:
347*b5893f02SDimitry Andric           return ArgType::Invalid();
348*b5893f02SDimitry Andric       }
349*b5893f02SDimitry Andric     case ConversionSpecifier::CArg:
350*b5893f02SDimitry Andric     case ConversionSpecifier::SArg:
351*b5893f02SDimitry Andric       // FIXME: Mac OS X specific?
352*b5893f02SDimitry Andric       switch (LM.getKind()) {
353*b5893f02SDimitry Andric         case LengthModifier::None:
354*b5893f02SDimitry Andric         case LengthModifier::AsWide:
355*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
356*b5893f02SDimitry Andric         case LengthModifier::AsAllocate:
357*b5893f02SDimitry Andric         case LengthModifier::AsMAllocate:
358*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
359*b5893f02SDimitry Andric         case LengthModifier::AsShort:
360*b5893f02SDimitry Andric           if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
361*b5893f02SDimitry Andric             return ArgType::PtrTo(ArgType::AnyCharTy);
362*b5893f02SDimitry Andric           LLVM_FALLTHROUGH;
363*b5893f02SDimitry Andric         default:
364*b5893f02SDimitry Andric           return ArgType::Invalid();
365*b5893f02SDimitry Andric       }
366*b5893f02SDimitry Andric 
367*b5893f02SDimitry Andric     // Pointer.
368*b5893f02SDimitry Andric     case ConversionSpecifier::pArg:
369*b5893f02SDimitry Andric       return ArgType::PtrTo(ArgType::CPointerTy);
370*b5893f02SDimitry Andric 
371*b5893f02SDimitry Andric     // Write-back.
372*b5893f02SDimitry Andric     case ConversionSpecifier::nArg:
373*b5893f02SDimitry Andric       switch (LM.getKind()) {
374*b5893f02SDimitry Andric         case LengthModifier::None:
375*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.IntTy);
376*b5893f02SDimitry Andric         case LengthModifier::AsChar:
377*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.SignedCharTy);
378*b5893f02SDimitry Andric         case LengthModifier::AsShort:
379*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.ShortTy);
380*b5893f02SDimitry Andric         case LengthModifier::AsLong:
381*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongTy);
382*b5893f02SDimitry Andric         case LengthModifier::AsLongLong:
383*b5893f02SDimitry Andric         case LengthModifier::AsQuad:
384*b5893f02SDimitry Andric           return ArgType::PtrTo(Ctx.LongLongTy);
385*b5893f02SDimitry Andric         case LengthModifier::AsInt64:
386*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
387*b5893f02SDimitry Andric         case LengthModifier::AsIntMax:
388*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
389*b5893f02SDimitry Andric         case LengthModifier::AsSizeT:
390*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
391*b5893f02SDimitry Andric         case LengthModifier::AsPtrDiff:
392*b5893f02SDimitry Andric           return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
393*b5893f02SDimitry Andric         case LengthModifier::AsLongDouble:
394*b5893f02SDimitry Andric           return ArgType(); // FIXME: Is this a known extension?
395*b5893f02SDimitry Andric         case LengthModifier::AsAllocate:
396*b5893f02SDimitry Andric         case LengthModifier::AsMAllocate:
397*b5893f02SDimitry Andric         case LengthModifier::AsInt32:
398*b5893f02SDimitry Andric         case LengthModifier::AsInt3264:
399*b5893f02SDimitry Andric         case LengthModifier::AsWide:
400*b5893f02SDimitry Andric           return ArgType::Invalid();
401*b5893f02SDimitry Andric         }
402*b5893f02SDimitry Andric 
403*b5893f02SDimitry Andric     default:
404*b5893f02SDimitry Andric       break;
405*b5893f02SDimitry Andric   }
406*b5893f02SDimitry Andric 
407*b5893f02SDimitry Andric   return ArgType();
408*b5893f02SDimitry Andric }
409*b5893f02SDimitry Andric 
fixType(QualType QT,QualType RawQT,const LangOptions & LangOpt,ASTContext & Ctx)410*b5893f02SDimitry Andric bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
411*b5893f02SDimitry Andric                              const LangOptions &LangOpt,
412*b5893f02SDimitry Andric                              ASTContext &Ctx) {
413*b5893f02SDimitry Andric 
414*b5893f02SDimitry Andric   // %n is different from other conversion specifiers; don't try to fix it.
415*b5893f02SDimitry Andric   if (CS.getKind() == ConversionSpecifier::nArg)
416*b5893f02SDimitry Andric     return false;
417*b5893f02SDimitry Andric 
418*b5893f02SDimitry Andric   if (!QT->isPointerType())
419*b5893f02SDimitry Andric     return false;
420*b5893f02SDimitry Andric 
421*b5893f02SDimitry Andric   QualType PT = QT->getPointeeType();
422*b5893f02SDimitry Andric 
423*b5893f02SDimitry Andric   // If it's an enum, get its underlying type.
424*b5893f02SDimitry Andric   if (const EnumType *ETy = PT->getAs<EnumType>()) {
425*b5893f02SDimitry Andric     // Don't try to fix incomplete enums.
426*b5893f02SDimitry Andric     if (!ETy->getDecl()->isComplete())
427*b5893f02SDimitry Andric       return false;
428*b5893f02SDimitry Andric     PT = ETy->getDecl()->getIntegerType();
429*b5893f02SDimitry Andric   }
430*b5893f02SDimitry Andric 
431*b5893f02SDimitry Andric   const BuiltinType *BT = PT->getAs<BuiltinType>();
432*b5893f02SDimitry Andric   if (!BT)
433*b5893f02SDimitry Andric     return false;
434*b5893f02SDimitry Andric 
435*b5893f02SDimitry Andric   // Pointer to a character.
436*b5893f02SDimitry Andric   if (PT->isAnyCharacterType()) {
437*b5893f02SDimitry Andric     CS.setKind(ConversionSpecifier::sArg);
438*b5893f02SDimitry Andric     if (PT->isWideCharType())
439*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsWideChar);
440*b5893f02SDimitry Andric     else
441*b5893f02SDimitry Andric       LM.setKind(LengthModifier::None);
442*b5893f02SDimitry Andric 
443*b5893f02SDimitry Andric     // If we know the target array length, we can use it as a field width.
444*b5893f02SDimitry Andric     if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
445*b5893f02SDimitry Andric       if (CAT->getSizeModifier() == ArrayType::Normal)
446*b5893f02SDimitry Andric         FieldWidth = OptionalAmount(OptionalAmount::Constant,
447*b5893f02SDimitry Andric                                     CAT->getSize().getZExtValue() - 1,
448*b5893f02SDimitry Andric                                     "", 0, false);
449*b5893f02SDimitry Andric 
450*b5893f02SDimitry Andric     }
451*b5893f02SDimitry Andric     return true;
452*b5893f02SDimitry Andric   }
453*b5893f02SDimitry Andric 
454*b5893f02SDimitry Andric   // Figure out the length modifier.
455*b5893f02SDimitry Andric   switch (BT->getKind()) {
456*b5893f02SDimitry Andric     // no modifier
457*b5893f02SDimitry Andric     case BuiltinType::UInt:
458*b5893f02SDimitry Andric     case BuiltinType::Int:
459*b5893f02SDimitry Andric     case BuiltinType::Float:
460*b5893f02SDimitry Andric       LM.setKind(LengthModifier::None);
461*b5893f02SDimitry Andric       break;
462*b5893f02SDimitry Andric 
463*b5893f02SDimitry Andric     // hh
464*b5893f02SDimitry Andric     case BuiltinType::Char_U:
465*b5893f02SDimitry Andric     case BuiltinType::UChar:
466*b5893f02SDimitry Andric     case BuiltinType::Char_S:
467*b5893f02SDimitry Andric     case BuiltinType::SChar:
468*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsChar);
469*b5893f02SDimitry Andric       break;
470*b5893f02SDimitry Andric 
471*b5893f02SDimitry Andric     // h
472*b5893f02SDimitry Andric     case BuiltinType::Short:
473*b5893f02SDimitry Andric     case BuiltinType::UShort:
474*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsShort);
475*b5893f02SDimitry Andric       break;
476*b5893f02SDimitry Andric 
477*b5893f02SDimitry Andric     // l
478*b5893f02SDimitry Andric     case BuiltinType::Long:
479*b5893f02SDimitry Andric     case BuiltinType::ULong:
480*b5893f02SDimitry Andric     case BuiltinType::Double:
481*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsLong);
482*b5893f02SDimitry Andric       break;
483*b5893f02SDimitry Andric 
484*b5893f02SDimitry Andric     // ll
485*b5893f02SDimitry Andric     case BuiltinType::LongLong:
486*b5893f02SDimitry Andric     case BuiltinType::ULongLong:
487*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsLongLong);
488*b5893f02SDimitry Andric       break;
489*b5893f02SDimitry Andric 
490*b5893f02SDimitry Andric     // L
491*b5893f02SDimitry Andric     case BuiltinType::LongDouble:
492*b5893f02SDimitry Andric       LM.setKind(LengthModifier::AsLongDouble);
493*b5893f02SDimitry Andric       break;
494*b5893f02SDimitry Andric 
495*b5893f02SDimitry Andric     // Don't know.
496*b5893f02SDimitry Andric     default:
497*b5893f02SDimitry Andric       return false;
498*b5893f02SDimitry Andric   }
499*b5893f02SDimitry Andric 
500*b5893f02SDimitry Andric   // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
501*b5893f02SDimitry Andric   if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
502*b5893f02SDimitry Andric     namedTypeToLengthModifier(PT, LM);
503*b5893f02SDimitry Andric 
504*b5893f02SDimitry Andric   // If fixing the length modifier was enough, we are done.
505*b5893f02SDimitry Andric   if (hasValidLengthModifier(Ctx.getTargetInfo())) {
506*b5893f02SDimitry Andric     const analyze_scanf::ArgType &AT = getArgType(Ctx);
507*b5893f02SDimitry Andric     if (AT.isValid() && AT.matchesType(Ctx, QT))
508*b5893f02SDimitry Andric       return true;
509*b5893f02SDimitry Andric   }
510*b5893f02SDimitry Andric 
511*b5893f02SDimitry Andric   // Figure out the conversion specifier.
512*b5893f02SDimitry Andric   if (PT->isRealFloatingType())
513*b5893f02SDimitry Andric     CS.setKind(ConversionSpecifier::fArg);
514*b5893f02SDimitry Andric   else if (PT->isSignedIntegerType())
515*b5893f02SDimitry Andric     CS.setKind(ConversionSpecifier::dArg);
516*b5893f02SDimitry Andric   else if (PT->isUnsignedIntegerType())
517*b5893f02SDimitry Andric     CS.setKind(ConversionSpecifier::uArg);
518*b5893f02SDimitry Andric   else
519*b5893f02SDimitry Andric     llvm_unreachable("Unexpected type");
520*b5893f02SDimitry Andric 
521*b5893f02SDimitry Andric   return true;
522*b5893f02SDimitry Andric }
523*b5893f02SDimitry Andric 
toString(raw_ostream & os) const524*b5893f02SDimitry Andric void ScanfSpecifier::toString(raw_ostream &os) const {
525*b5893f02SDimitry Andric   os << "%";
526*b5893f02SDimitry Andric 
527*b5893f02SDimitry Andric   if (usesPositionalArg())
528*b5893f02SDimitry Andric     os << getPositionalArgIndex() << "$";
529*b5893f02SDimitry Andric   if (SuppressAssignment)
530*b5893f02SDimitry Andric     os << "*";
531*b5893f02SDimitry Andric 
532*b5893f02SDimitry Andric   FieldWidth.toString(os);
533*b5893f02SDimitry Andric   os << LM.toString();
534*b5893f02SDimitry Andric   os << CS.toString();
535*b5893f02SDimitry Andric }
536*b5893f02SDimitry Andric 
ParseScanfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)537*b5893f02SDimitry Andric bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
538*b5893f02SDimitry Andric                                                     const char *I,
539*b5893f02SDimitry Andric                                                     const char *E,
540*b5893f02SDimitry Andric                                                     const LangOptions &LO,
541*b5893f02SDimitry Andric                                                     const TargetInfo &Target) {
542*b5893f02SDimitry Andric 
543*b5893f02SDimitry Andric   unsigned argIndex = 0;
544*b5893f02SDimitry Andric 
545*b5893f02SDimitry Andric   // Keep looking for a format specifier until we have exhausted the string.
546*b5893f02SDimitry Andric   while (I != E) {
547*b5893f02SDimitry Andric     const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
548*b5893f02SDimitry Andric                                                           LO, Target);
549*b5893f02SDimitry Andric     // Did a fail-stop error of any kind occur when parsing the specifier?
550*b5893f02SDimitry Andric     // If so, don't do any more processing.
551*b5893f02SDimitry Andric     if (FSR.shouldStop())
552*b5893f02SDimitry Andric       return true;
553*b5893f02SDimitry Andric       // Did we exhaust the string or encounter an error that
554*b5893f02SDimitry Andric       // we can recover from?
555*b5893f02SDimitry Andric     if (!FSR.hasValue())
556*b5893f02SDimitry Andric       continue;
557*b5893f02SDimitry Andric       // We have a format specifier.  Pass it to the callback.
558*b5893f02SDimitry Andric     if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
559*b5893f02SDimitry Andric                                 I - FSR.getStart())) {
560*b5893f02SDimitry Andric       return true;
561*b5893f02SDimitry Andric     }
562*b5893f02SDimitry Andric   }
563*b5893f02SDimitry Andric   assert(I == E && "Format string not exhausted");
564*b5893f02SDimitry Andric   return false;
565*b5893f02SDimitry Andric }
566