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