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