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