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