blob: bda97c57c87c06edc8e40db00c2d016075b942c2 [file] [log] [blame]
Ted Kremeneka1ef09402010-07-16 02:11:31 +00001//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Handling of format string in scanf and friends. The structure of format
11// strings for fscanf() are described in C99 7.19.6.2.
12//
13//===----------------------------------------------------------------------===//
14
Tim Northover314fbfa2018-11-02 13:14:11 +000015#include "clang/AST/FormatString.h"
Ted Kremeneka1ef09402010-07-16 02:11:31 +000016#include "FormatStringParsing.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000017#include "clang/Basic/TargetInfo.h"
Ted Kremeneka1ef09402010-07-16 02:11:31 +000018
Hans Wennborgc3b3da02012-08-07 08:11:26 +000019using clang::analyze_format_string::ArgType;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000020using clang::analyze_format_string::FormatStringHandler;
21using clang::analyze_format_string::LengthModifier;
22using clang::analyze_format_string::OptionalAmount;
Ted Kremenek4407ea42010-07-20 20:04:47 +000023using clang::analyze_format_string::ConversionSpecifier;
Ted Kremenekf03e6d852010-07-20 20:04:27 +000024using clang::analyze_scanf::ScanfConversionSpecifier;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000025using clang::analyze_scanf::ScanfSpecifier;
Dan Gohman28ade552010-07-26 21:25:24 +000026using clang::UpdateOnReturn;
Hans Wennborgb1a5e092011-12-10 13:20:11 +000027using namespace clang;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000028
29typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
30 ScanfSpecifierResult;
31
32static bool ParseScanList(FormatStringHandler &H,
Ted Kremenekf03e6d852010-07-20 20:04:27 +000033 ScanfConversionSpecifier &CS,
Ted Kremeneka1ef09402010-07-16 02:11:31 +000034 const char *&Beg, const char *E) {
35 const char *I = Beg;
36 const char *start = I - 1;
37 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
38
39 // No more characters?
40 if (I == E) {
41 H.HandleIncompleteScanList(start, I);
42 return true;
43 }
Fangrui Song6907ce22018-07-30 19:24:48 +000044
Ted Kremeneka1ef09402010-07-16 02:11:31 +000045 // Special case: ']' is the first character.
46 if (*I == ']') {
47 if (++I == E) {
Ted Kremenekd7b31cc2010-07-16 18:28:03 +000048 H.HandleIncompleteScanList(start, I - 1);
Ted Kremeneka1ef09402010-07-16 02:11:31 +000049 return true;
50 }
51 }
52
Hans Wennborg802df132014-05-02 18:12:30 +000053 // Special case: "^]" are the first characters.
Hans Wennborgdf51ee62014-04-29 19:42:27 +000054 if (I + 1 != E && I[0] == '^' && I[1] == ']') {
55 I += 2;
56 if (I == E) {
57 H.HandleIncompleteScanList(start, I - 1);
58 return true;
59 }
60 }
61
Ted Kremeneka1ef09402010-07-16 02:11:31 +000062 // Look for a ']' character which denotes the end of the scan list.
63 while (*I != ']') {
64 if (++I == E) {
Ted Kremenekd7b31cc2010-07-16 18:28:03 +000065 H.HandleIncompleteScanList(start, I - 1);
Ted Kremeneka1ef09402010-07-16 02:11:31 +000066 return true;
67 }
Fangrui Song6907ce22018-07-30 19:24:48 +000068 }
Ted Kremeneka1ef09402010-07-16 02:11:31 +000069
70 CS.setEndScanList(I);
71 return false;
72}
73
74// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
75// We can possibly refactor.
76static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
77 const char *&Beg,
78 const char *E,
Hans Wennborg23926bd2011-12-15 10:25:47 +000079 unsigned &argIndex,
Jordan Rose510260c2012-09-13 02:11:03 +000080 const LangOptions &LO,
81 const TargetInfo &Target) {
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +000082 using namespace clang::analyze_format_string;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000083 using namespace clang::analyze_scanf;
84 const char *I = Beg;
Craig Topper25542942014-05-20 04:30:07 +000085 const char *Start = nullptr;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000086 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
87
88 // Look for a '%' character that indicates the start of a format specifier.
89 for ( ; I != E ; ++I) {
90 char c = *I;
91 if (c == '\0') {
92 // Detect spurious null characters, which are likely errors.
93 H.HandleNullChar(I);
94 return true;
95 }
96 if (c == '%') {
97 Start = I++; // Record the start of the format specifier.
98 break;
99 }
100 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000101
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000102 // No format specifier found?
103 if (!Start)
104 return false;
Fangrui Song6907ce22018-07-30 19:24:48 +0000105
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000106 if (I == E) {
107 // No more characters left?
108 H.HandleIncompleteSpecifier(Start, E - Start);
109 return true;
110 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000111
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000112 ScanfSpecifier FS;
113 if (ParseArgPosition(H, FS, Start, I, E))
114 return true;
115
116 if (I == E) {
117 // No more characters left?
118 H.HandleIncompleteSpecifier(Start, E - Start);
119 return true;
120 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000121
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000122 // Look for '*' flag if it is present.
123 if (*I == '*') {
124 FS.setSuppressAssignment(I);
125 if (++I == E) {
126 H.HandleIncompleteSpecifier(Start, E - Start);
127 return true;
128 }
129 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000130
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000131 // Look for the field width (if any). Unlike printf, this is either
132 // a fixed integer or isn't present.
133 const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
134 if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
135 assert(Amt.getHowSpecified() == OptionalAmount::Constant);
136 FS.setFieldWidth(Amt);
137
138 if (I == E) {
139 // No more characters left?
140 H.HandleIncompleteSpecifier(Start, E - Start);
141 return true;
142 }
143 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000144
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000145 // Look for the length modifier.
Hans Wennborg23926bd2011-12-15 10:25:47 +0000146 if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000147 // No more characters left?
148 H.HandleIncompleteSpecifier(Start, E - Start);
149 return true;
150 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000151
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000152 // Detect spurious null characters, which are likely errors.
153 if (*I == '\0') {
154 H.HandleNullChar(I);
155 return true;
156 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000157
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000158 // Finally, look for the conversion specifier.
159 const char *conversionPosition = I++;
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000160 ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000161 switch (*conversionPosition) {
162 default:
163 break;
Ted Kremenek4407ea42010-07-20 20:04:47 +0000164 case '%': k = ConversionSpecifier::PercentArg; break;
165 case 'A': k = ConversionSpecifier::AArg; break;
166 case 'E': k = ConversionSpecifier::EArg; break;
167 case 'F': k = ConversionSpecifier::FArg; break;
168 case 'G': k = ConversionSpecifier::GArg; break;
169 case 'X': k = ConversionSpecifier::XArg; break;
170 case 'a': k = ConversionSpecifier::aArg; break;
171 case 'd': k = ConversionSpecifier::dArg; break;
172 case 'e': k = ConversionSpecifier::eArg; break;
173 case 'f': k = ConversionSpecifier::fArg; break;
174 case 'g': k = ConversionSpecifier::gArg; break;
175 case 'i': k = ConversionSpecifier::iArg; break;
176 case 'n': k = ConversionSpecifier::nArg; break;
177 case 'c': k = ConversionSpecifier::cArg; break;
178 case 'C': k = ConversionSpecifier::CArg; break;
179 case 'S': k = ConversionSpecifier::SArg; break;
180 case '[': k = ConversionSpecifier::ScanListArg; break;
181 case 'u': k = ConversionSpecifier::uArg; break;
182 case 'x': k = ConversionSpecifier::xArg; break;
183 case 'o': k = ConversionSpecifier::oArg; break;
184 case 's': k = ConversionSpecifier::sArg; break;
185 case 'p': k = ConversionSpecifier::pArg; break;
Jordan Rose510260c2012-09-13 02:11:03 +0000186 // Apple extensions
187 // Apple-specific
188 case 'D':
189 if (Target.getTriple().isOSDarwin())
190 k = ConversionSpecifier::DArg;
191 break;
192 case 'O':
193 if (Target.getTriple().isOSDarwin())
194 k = ConversionSpecifier::OArg;
195 break;
196 case 'U':
197 if (Target.getTriple().isOSDarwin())
198 k = ConversionSpecifier::UArg;
199 break;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000200 }
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000201 ScanfConversionSpecifier CS(conversionPosition, k);
202 if (k == ScanfConversionSpecifier::ScanListArg) {
Hans Wennborg32f115f2012-01-12 14:44:54 +0000203 if (ParseScanList(H, CS, I, E))
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000204 return true;
205 }
206 FS.setConversionSpecifier(CS);
207 if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
208 && !FS.usesPositionalArg())
209 FS.setArgIndex(argIndex++);
Fangrui Song6907ce22018-07-30 19:24:48 +0000210
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000211 // FIXME: '%' and '*' doesn't make sense. Issue a warning.
212 // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000213
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000214 if (k == ScanfConversionSpecifier::InvalidSpecifier) {
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000215 unsigned Len = I - Beg;
216 if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
217 CS.setEndScanList(Beg + Len);
218 FS.setConversionSpecifier(CS);
219 }
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000220 // Assume the conversion takes one argument.
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000221 return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000222 }
223 return ScanfSpecifierResult(Start, FS);
224}
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000225
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000226ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000227 const ScanfConversionSpecifier &CS = getConversionSpecifier();
228
229 if (!CS.consumesDataArgument())
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000230 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000231
232 switch(CS.getKind()) {
233 // Signed int.
234 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000235 case ConversionSpecifier::DArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000236 case ConversionSpecifier::iArg:
237 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000238 case LengthModifier::None:
239 return ArgType::PtrTo(Ctx.IntTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000240 case LengthModifier::AsChar:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000241 return ArgType::PtrTo(ArgType::AnyCharTy);
242 case LengthModifier::AsShort:
243 return ArgType::PtrTo(Ctx.ShortTy);
244 case LengthModifier::AsLong:
245 return ArgType::PtrTo(Ctx.LongTy);
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000246 case LengthModifier::AsLongLong:
247 case LengthModifier::AsQuad:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000248 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000249 case LengthModifier::AsInt64:
250 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000251 case LengthModifier::AsIntMax:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000252 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000253 case LengthModifier::AsSizeT:
Alexander Shaposhnikov593e4bb2017-07-20 20:11:47 +0000254 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000255 case LengthModifier::AsPtrDiff:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000256 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
Ted Kremenek6fa57272012-01-24 21:29:54 +0000257 case LengthModifier::AsLongDouble:
258 // GNU extension.
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000259 return ArgType::PtrTo(Ctx.LongLongTy);
260 case LengthModifier::AsAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000261 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000262 case LengthModifier::AsInt32:
263 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000264 case LengthModifier::AsWide:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000265 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000266 }
267
268 // Unsigned int.
269 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000270 case ConversionSpecifier::OArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000271 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000272 case ConversionSpecifier::UArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000273 case ConversionSpecifier::xArg:
274 case ConversionSpecifier::XArg:
275 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000276 case LengthModifier::None:
277 return ArgType::PtrTo(Ctx.UnsignedIntTy);
278 case LengthModifier::AsChar:
279 return ArgType::PtrTo(Ctx.UnsignedCharTy);
280 case LengthModifier::AsShort:
281 return ArgType::PtrTo(Ctx.UnsignedShortTy);
282 case LengthModifier::AsLong:
283 return ArgType::PtrTo(Ctx.UnsignedLongTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000284 case LengthModifier::AsLongLong:
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000285 case LengthModifier::AsQuad:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000286 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000287 case LengthModifier::AsInt64:
288 return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000289 case LengthModifier::AsIntMax:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000290 return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000291 case LengthModifier::AsSizeT:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000292 return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000293 case LengthModifier::AsPtrDiff:
Alexander Shaposhnikov195b25c2017-09-28 23:11:31 +0000294 return ArgType::PtrTo(
295 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
Ted Kremenek6fa57272012-01-24 21:29:54 +0000296 case LengthModifier::AsLongDouble:
297 // GNU extension.
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000298 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
299 case LengthModifier::AsAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000300 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000301 case LengthModifier::AsInt32:
302 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000303 case LengthModifier::AsWide:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000304 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000305 }
306
307 // Float.
308 case ConversionSpecifier::aArg:
309 case ConversionSpecifier::AArg:
310 case ConversionSpecifier::eArg:
311 case ConversionSpecifier::EArg:
312 case ConversionSpecifier::fArg:
313 case ConversionSpecifier::FArg:
314 case ConversionSpecifier::gArg:
315 case ConversionSpecifier::GArg:
316 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000317 case LengthModifier::None:
318 return ArgType::PtrTo(Ctx.FloatTy);
319 case LengthModifier::AsLong:
320 return ArgType::PtrTo(Ctx.DoubleTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000321 case LengthModifier::AsLongDouble:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000322 return ArgType::PtrTo(Ctx.LongDoubleTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000323 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000324 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000325 }
326
327 // Char, string and scanlist.
328 case ConversionSpecifier::cArg:
329 case ConversionSpecifier::sArg:
330 case ConversionSpecifier::ScanListArg:
331 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000332 case LengthModifier::None:
333 return ArgType::PtrTo(ArgType::AnyCharTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000334 case LengthModifier::AsLong:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000335 case LengthModifier::AsWide:
Hans Wennborg0d81e012013-05-10 10:08:40 +0000336 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg6073e312012-01-12 17:11:12 +0000337 case LengthModifier::AsAllocate:
338 case LengthModifier::AsMAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000339 return ArgType::PtrTo(ArgType::CStrTy);
Hans Wennborg1b231582014-09-04 21:39:52 +0000340 case LengthModifier::AsShort:
341 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
342 return ArgType::PtrTo(ArgType::AnyCharTy);
Galina Kistanovade7e2212017-06-03 06:23:51 +0000343 LLVM_FALLTHROUGH;
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000344 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000345 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000346 }
347 case ConversionSpecifier::CArg:
348 case ConversionSpecifier::SArg:
349 // FIXME: Mac OS X specific?
Hans Wennborg6073e312012-01-12 17:11:12 +0000350 switch (LM.getKind()) {
351 case LengthModifier::None:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000352 case LengthModifier::AsWide:
Hans Wennborg0d81e012013-05-10 10:08:40 +0000353 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg6073e312012-01-12 17:11:12 +0000354 case LengthModifier::AsAllocate:
355 case LengthModifier::AsMAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000356 return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
Hans Wennborg1b231582014-09-04 21:39:52 +0000357 case LengthModifier::AsShort:
358 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
359 return ArgType::PtrTo(ArgType::AnyCharTy);
Galina Kistanovade7e2212017-06-03 06:23:51 +0000360 LLVM_FALLTHROUGH;
Hans Wennborg6073e312012-01-12 17:11:12 +0000361 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000362 return ArgType::Invalid();
Hans Wennborg6073e312012-01-12 17:11:12 +0000363 }
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000364
365 // Pointer.
366 case ConversionSpecifier::pArg:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000367 return ArgType::PtrTo(ArgType::CPointerTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000368
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000369 // Write-back.
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000370 case ConversionSpecifier::nArg:
Hans Wennborgabc1e222012-08-07 09:13:19 +0000371 switch (LM.getKind()) {
372 case LengthModifier::None:
373 return ArgType::PtrTo(Ctx.IntTy);
374 case LengthModifier::AsChar:
375 return ArgType::PtrTo(Ctx.SignedCharTy);
376 case LengthModifier::AsShort:
377 return ArgType::PtrTo(Ctx.ShortTy);
378 case LengthModifier::AsLong:
379 return ArgType::PtrTo(Ctx.LongTy);
380 case LengthModifier::AsLongLong:
381 case LengthModifier::AsQuad:
382 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000383 case LengthModifier::AsInt64:
384 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborgabc1e222012-08-07 09:13:19 +0000385 case LengthModifier::AsIntMax:
386 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
387 case LengthModifier::AsSizeT:
Alexander Shaposhnikov593e4bb2017-07-20 20:11:47 +0000388 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
Hans Wennborgabc1e222012-08-07 09:13:19 +0000389 case LengthModifier::AsPtrDiff:
390 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
391 case LengthModifier::AsLongDouble:
392 return ArgType(); // FIXME: Is this a known extension?
393 case LengthModifier::AsAllocate:
394 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000395 case LengthModifier::AsInt32:
396 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000397 case LengthModifier::AsWide:
Hans Wennborgabc1e222012-08-07 09:13:19 +0000398 return ArgType::Invalid();
399 }
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000400
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000401 default:
402 break;
403 }
404
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000405 return ArgType();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000406}
407
Jordan Rose177b0a32014-03-20 03:32:39 +0000408bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
409 const LangOptions &LangOpt,
Hans Wennborgd99d6882012-02-15 09:59:46 +0000410 ASTContext &Ctx) {
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000411
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000412 // %n is different from other conversion specifiers; don't try to fix it.
413 if (CS.getKind() == ConversionSpecifier::nArg)
414 return false;
415
Jordan Rose177b0a32014-03-20 03:32:39 +0000416 if (!QT->isPointerType())
417 return false;
418
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000419 QualType PT = QT->getPointeeType();
Jordan Rose614e72b2012-06-04 22:49:02 +0000420
421 // If it's an enum, get its underlying type.
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000422 if (const EnumType *ETy = PT->getAs<EnumType>()) {
423 // Don't try to fix incomplete enums.
424 if (!ETy->getDecl()->isComplete())
425 return false;
Jordan Rose177b0a32014-03-20 03:32:39 +0000426 PT = ETy->getDecl()->getIntegerType();
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000427 }
Jordan Rose177b0a32014-03-20 03:32:39 +0000428
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000429 const BuiltinType *BT = PT->getAs<BuiltinType>();
430 if (!BT)
431 return false;
432
433 // Pointer to a character.
434 if (PT->isAnyCharacterType()) {
435 CS.setKind(ConversionSpecifier::sArg);
436 if (PT->isWideCharType())
437 LM.setKind(LengthModifier::AsWideChar);
438 else
439 LM.setKind(LengthModifier::None);
Jordan Rose177b0a32014-03-20 03:32:39 +0000440
441 // If we know the target array length, we can use it as a field width.
442 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
443 if (CAT->getSizeModifier() == ArrayType::Normal)
444 FieldWidth = OptionalAmount(OptionalAmount::Constant,
445 CAT->getSize().getZExtValue() - 1,
446 "", 0, false);
447
448 }
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000449 return true;
450 }
451
452 // Figure out the length modifier.
453 switch (BT->getKind()) {
454 // no modifier
455 case BuiltinType::UInt:
456 case BuiltinType::Int:
457 case BuiltinType::Float:
458 LM.setKind(LengthModifier::None);
459 break;
460
461 // hh
462 case BuiltinType::Char_U:
463 case BuiltinType::UChar:
464 case BuiltinType::Char_S:
465 case BuiltinType::SChar:
466 LM.setKind(LengthModifier::AsChar);
467 break;
468
469 // h
470 case BuiltinType::Short:
471 case BuiltinType::UShort:
472 LM.setKind(LengthModifier::AsShort);
473 break;
474
475 // l
476 case BuiltinType::Long:
477 case BuiltinType::ULong:
478 case BuiltinType::Double:
479 LM.setKind(LengthModifier::AsLong);
480 break;
481
482 // ll
483 case BuiltinType::LongLong:
484 case BuiltinType::ULongLong:
485 LM.setKind(LengthModifier::AsLongLong);
486 break;
487
488 // L
489 case BuiltinType::LongDouble:
490 LM.setKind(LengthModifier::AsLongDouble);
491 break;
492
493 // Don't know.
494 default:
495 return false;
496 }
497
498 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
Richard Smith2bf7fdb2013-01-02 11:42:31 +0000499 if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
Hans Wennborg08574d32012-07-27 19:17:46 +0000500 namedTypeToLengthModifier(PT, LM);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000501
Hans Wennborgd99d6882012-02-15 09:59:46 +0000502 // If fixing the length modifier was enough, we are done.
Jordan Rose92303592012-09-08 04:00:03 +0000503 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
504 const analyze_scanf::ArgType &AT = getArgType(Ctx);
505 if (AT.isValid() && AT.matchesType(Ctx, QT))
506 return true;
507 }
Hans Wennborgd99d6882012-02-15 09:59:46 +0000508
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000509 // Figure out the conversion specifier.
510 if (PT->isRealFloatingType())
511 CS.setKind(ConversionSpecifier::fArg);
512 else if (PT->isSignedIntegerType())
513 CS.setKind(ConversionSpecifier::dArg);
Hans Wennborgd99d6882012-02-15 09:59:46 +0000514 else if (PT->isUnsignedIntegerType())
515 CS.setKind(ConversionSpecifier::uArg);
516 else
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000517 llvm_unreachable("Unexpected type");
518
519 return true;
520}
521
522void ScanfSpecifier::toString(raw_ostream &os) const {
523 os << "%";
524
525 if (usesPositionalArg())
526 os << getPositionalArgIndex() << "$";
527 if (SuppressAssignment)
528 os << "*";
529
530 FieldWidth.toString(os);
531 os << LM.toString();
532 os << CS.toString();
533}
534
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000535bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
536 const char *I,
Hans Wennborg23926bd2011-12-15 10:25:47 +0000537 const char *E,
Jordan Rose510260c2012-09-13 02:11:03 +0000538 const LangOptions &LO,
539 const TargetInfo &Target) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000540
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000541 unsigned argIndex = 0;
Fangrui Song6907ce22018-07-30 19:24:48 +0000542
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000543 // Keep looking for a format specifier until we have exhausted the string.
544 while (I != E) {
Hans Wennborg23926bd2011-12-15 10:25:47 +0000545 const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
Jordan Rose510260c2012-09-13 02:11:03 +0000546 LO, Target);
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000547 // Did a fail-stop error of any kind occur when parsing the specifier?
548 // If so, don't do any more processing.
549 if (FSR.shouldStop())
Dmitri Gribenko76bb5cabfa2012-09-10 21:20:09 +0000550 return true;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000551 // Did we exhaust the string or encounter an error that
552 // we can recover from?
553 if (!FSR.hasValue())
554 continue;
555 // We have a format specifier. Pass it to the callback.
556 if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
557 I - FSR.getStart())) {
558 return true;
559 }
560 }
561 assert(I == E && "Format string not exhausted");
562 return false;
563}