blob: 8d763f28e57fd23c09681851703f34b3cd3afc63 [file] [log] [blame]
Ted Kremeneka1ef09402010-07-16 02:11:31 +00001//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Ted Kremeneka1ef09402010-07-16 02:11:31 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Handling of format string in scanf and friends. The structure of format
10// strings for fscanf() are described in C99 7.19.6.2.
11//
12//===----------------------------------------------------------------------===//
13
Tim Northover314fbfa2018-11-02 13:14:11 +000014#include "clang/AST/FormatString.h"
Ted Kremeneka1ef09402010-07-16 02:11:31 +000015#include "FormatStringParsing.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000016#include "clang/Basic/TargetInfo.h"
Ted Kremeneka1ef09402010-07-16 02:11:31 +000017
Hans Wennborgc3b3da02012-08-07 08:11:26 +000018using clang::analyze_format_string::ArgType;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000019using clang::analyze_format_string::FormatStringHandler;
20using clang::analyze_format_string::LengthModifier;
21using clang::analyze_format_string::OptionalAmount;
Ted Kremenek4407ea42010-07-20 20:04:47 +000022using clang::analyze_format_string::ConversionSpecifier;
Ted Kremenekf03e6d852010-07-20 20:04:27 +000023using clang::analyze_scanf::ScanfConversionSpecifier;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000024using clang::analyze_scanf::ScanfSpecifier;
Dan Gohman28ade552010-07-26 21:25:24 +000025using clang::UpdateOnReturn;
Hans Wennborgb1a5e092011-12-10 13:20:11 +000026using namespace clang;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000027
28typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
29 ScanfSpecifierResult;
30
31static bool ParseScanList(FormatStringHandler &H,
Ted Kremenekf03e6d852010-07-20 20:04:27 +000032 ScanfConversionSpecifier &CS,
Ted Kremeneka1ef09402010-07-16 02:11:31 +000033 const char *&Beg, const char *E) {
34 const char *I = Beg;
35 const char *start = I - 1;
36 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
37
38 // No more characters?
39 if (I == E) {
40 H.HandleIncompleteScanList(start, I);
41 return true;
42 }
Fangrui Song6907ce22018-07-30 19:24:48 +000043
Ted Kremeneka1ef09402010-07-16 02:11:31 +000044 // Special case: ']' is the first character.
45 if (*I == ']') {
46 if (++I == E) {
Ted Kremenekd7b31cc2010-07-16 18:28:03 +000047 H.HandleIncompleteScanList(start, I - 1);
Ted Kremeneka1ef09402010-07-16 02:11:31 +000048 return true;
49 }
50 }
51
Hans Wennborg802df132014-05-02 18:12:30 +000052 // Special case: "^]" are the first characters.
Hans Wennborgdf51ee62014-04-29 19:42:27 +000053 if (I + 1 != E && I[0] == '^' && I[1] == ']') {
54 I += 2;
55 if (I == E) {
56 H.HandleIncompleteScanList(start, I - 1);
57 return true;
58 }
59 }
60
Ted Kremeneka1ef09402010-07-16 02:11:31 +000061 // Look for a ']' character which denotes the end of the scan list.
62 while (*I != ']') {
63 if (++I == E) {
Ted Kremenekd7b31cc2010-07-16 18:28:03 +000064 H.HandleIncompleteScanList(start, I - 1);
Ted Kremeneka1ef09402010-07-16 02:11:31 +000065 return true;
66 }
Fangrui Song6907ce22018-07-30 19:24:48 +000067 }
Ted Kremeneka1ef09402010-07-16 02:11:31 +000068
69 CS.setEndScanList(I);
70 return false;
71}
72
73// FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
74// We can possibly refactor.
75static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
76 const char *&Beg,
77 const char *E,
Hans Wennborg23926bd2011-12-15 10:25:47 +000078 unsigned &argIndex,
Jordan Rose510260c2012-09-13 02:11:03 +000079 const LangOptions &LO,
80 const TargetInfo &Target) {
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +000081 using namespace clang::analyze_format_string;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000082 using namespace clang::analyze_scanf;
83 const char *I = Beg;
Craig Topper25542942014-05-20 04:30:07 +000084 const char *Start = nullptr;
Ted Kremeneka1ef09402010-07-16 02:11:31 +000085 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
86
87 // Look for a '%' character that indicates the start of a format specifier.
88 for ( ; I != E ; ++I) {
89 char c = *I;
90 if (c == '\0') {
91 // Detect spurious null characters, which are likely errors.
92 H.HandleNullChar(I);
93 return true;
94 }
95 if (c == '%') {
96 Start = I++; // Record the start of the format specifier.
97 break;
98 }
99 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000100
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000101 // No format specifier found?
102 if (!Start)
103 return false;
Fangrui Song6907ce22018-07-30 19:24:48 +0000104
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000105 if (I == E) {
106 // No more characters left?
107 H.HandleIncompleteSpecifier(Start, E - Start);
108 return true;
109 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000110
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000111 ScanfSpecifier FS;
112 if (ParseArgPosition(H, FS, Start, I, E))
113 return true;
114
115 if (I == E) {
116 // No more characters left?
117 H.HandleIncompleteSpecifier(Start, E - Start);
118 return true;
119 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000120
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000121 // Look for '*' flag if it is present.
122 if (*I == '*') {
123 FS.setSuppressAssignment(I);
124 if (++I == E) {
125 H.HandleIncompleteSpecifier(Start, E - Start);
126 return true;
127 }
128 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000129
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000130 // Look for the field width (if any). Unlike printf, this is either
131 // a fixed integer or isn't present.
132 const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
133 if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
134 assert(Amt.getHowSpecified() == OptionalAmount::Constant);
135 FS.setFieldWidth(Amt);
136
137 if (I == E) {
138 // No more characters left?
139 H.HandleIncompleteSpecifier(Start, E - Start);
140 return true;
141 }
142 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000143
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000144 // Look for the length modifier.
Rui Ueyama49a3ad22019-07-16 04:46:31 +0000145 if (ParseLengthModifier(FS, I, E, LO, /*IsScanf=*/true) && I == E) {
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000146 // No more characters left?
147 H.HandleIncompleteSpecifier(Start, E - Start);
148 return true;
149 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000150
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000151 // Detect spurious null characters, which are likely errors.
152 if (*I == '\0') {
153 H.HandleNullChar(I);
154 return true;
155 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000156
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000157 // Finally, look for the conversion specifier.
158 const char *conversionPosition = I++;
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000159 ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000160 switch (*conversionPosition) {
161 default:
162 break;
Ted Kremenek4407ea42010-07-20 20:04:47 +0000163 case '%': k = ConversionSpecifier::PercentArg; break;
164 case 'A': k = ConversionSpecifier::AArg; break;
165 case 'E': k = ConversionSpecifier::EArg; break;
166 case 'F': k = ConversionSpecifier::FArg; break;
167 case 'G': k = ConversionSpecifier::GArg; break;
168 case 'X': k = ConversionSpecifier::XArg; break;
169 case 'a': k = ConversionSpecifier::aArg; break;
170 case 'd': k = ConversionSpecifier::dArg; break;
171 case 'e': k = ConversionSpecifier::eArg; break;
172 case 'f': k = ConversionSpecifier::fArg; break;
173 case 'g': k = ConversionSpecifier::gArg; break;
174 case 'i': k = ConversionSpecifier::iArg; break;
175 case 'n': k = ConversionSpecifier::nArg; break;
176 case 'c': k = ConversionSpecifier::cArg; break;
177 case 'C': k = ConversionSpecifier::CArg; break;
178 case 'S': k = ConversionSpecifier::SArg; break;
179 case '[': k = ConversionSpecifier::ScanListArg; break;
180 case 'u': k = ConversionSpecifier::uArg; break;
181 case 'x': k = ConversionSpecifier::xArg; break;
182 case 'o': k = ConversionSpecifier::oArg; break;
183 case 's': k = ConversionSpecifier::sArg; break;
184 case 'p': k = ConversionSpecifier::pArg; break;
Jordan Rose510260c2012-09-13 02:11:03 +0000185 // Apple extensions
186 // Apple-specific
187 case 'D':
188 if (Target.getTriple().isOSDarwin())
189 k = ConversionSpecifier::DArg;
190 break;
191 case 'O':
192 if (Target.getTriple().isOSDarwin())
193 k = ConversionSpecifier::OArg;
194 break;
195 case 'U':
196 if (Target.getTriple().isOSDarwin())
197 k = ConversionSpecifier::UArg;
198 break;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000199 }
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000200 ScanfConversionSpecifier CS(conversionPosition, k);
201 if (k == ScanfConversionSpecifier::ScanListArg) {
Hans Wennborg32f115f2012-01-12 14:44:54 +0000202 if (ParseScanList(H, CS, I, E))
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000203 return true;
204 }
205 FS.setConversionSpecifier(CS);
206 if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
207 && !FS.usesPositionalArg())
208 FS.setArgIndex(argIndex++);
Fangrui Song6907ce22018-07-30 19:24:48 +0000209
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000210 // FIXME: '%' and '*' doesn't make sense. Issue a warning.
211 // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000212
Ted Kremenekf03e6d852010-07-20 20:04:27 +0000213 if (k == ScanfConversionSpecifier::InvalidSpecifier) {
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000214 unsigned Len = I - Beg;
215 if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
216 CS.setEndScanList(Beg + Len);
217 FS.setConversionSpecifier(CS);
218 }
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000219 // Assume the conversion takes one argument.
Bruno Cardoso Lopes0c18d032016-03-29 17:35:02 +0000220 return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000221 }
222 return ScanfSpecifierResult(Start, FS);
223}
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000224
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000225ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000226 const ScanfConversionSpecifier &CS = getConversionSpecifier();
227
228 if (!CS.consumesDataArgument())
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000229 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000230
231 switch(CS.getKind()) {
232 // Signed int.
233 case ConversionSpecifier::dArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000234 case ConversionSpecifier::DArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000235 case ConversionSpecifier::iArg:
236 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000237 case LengthModifier::None:
238 return ArgType::PtrTo(Ctx.IntTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000239 case LengthModifier::AsChar:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000240 return ArgType::PtrTo(ArgType::AnyCharTy);
241 case LengthModifier::AsShort:
242 return ArgType::PtrTo(Ctx.ShortTy);
243 case LengthModifier::AsLong:
244 return ArgType::PtrTo(Ctx.LongTy);
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000245 case LengthModifier::AsLongLong:
246 case LengthModifier::AsQuad:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000247 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000248 case LengthModifier::AsInt64:
249 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000250 case LengthModifier::AsIntMax:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000251 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000252 case LengthModifier::AsSizeT:
Alexander Shaposhnikov593e4bb2017-07-20 20:11:47 +0000253 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000254 case LengthModifier::AsPtrDiff:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000255 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
Ted Kremenek6fa57272012-01-24 21:29:54 +0000256 case LengthModifier::AsLongDouble:
257 // GNU extension.
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000258 return ArgType::PtrTo(Ctx.LongLongTy);
259 case LengthModifier::AsAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000260 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000261 case LengthModifier::AsInt32:
262 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000263 case LengthModifier::AsWide:
Matt Arsenault58fc8082019-01-29 20:49:54 +0000264 case LengthModifier::AsShortLong:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000265 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000266 }
Matt Arsenault58fc8082019-01-29 20:49:54 +0000267 llvm_unreachable("Unsupported LengthModifier Type");
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000268
269 // Unsigned int.
270 case ConversionSpecifier::oArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000271 case ConversionSpecifier::OArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000272 case ConversionSpecifier::uArg:
Jordan Rose510260c2012-09-13 02:11:03 +0000273 case ConversionSpecifier::UArg:
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000274 case ConversionSpecifier::xArg:
275 case ConversionSpecifier::XArg:
276 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000277 case LengthModifier::None:
278 return ArgType::PtrTo(Ctx.UnsignedIntTy);
279 case LengthModifier::AsChar:
280 return ArgType::PtrTo(Ctx.UnsignedCharTy);
281 case LengthModifier::AsShort:
282 return ArgType::PtrTo(Ctx.UnsignedShortTy);
283 case LengthModifier::AsLong:
284 return ArgType::PtrTo(Ctx.UnsignedLongTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000285 case LengthModifier::AsLongLong:
Hans Wennborg9bc9bcc2012-02-16 16:34:54 +0000286 case LengthModifier::AsQuad:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000287 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000288 case LengthModifier::AsInt64:
289 return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000290 case LengthModifier::AsIntMax:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000291 return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000292 case LengthModifier::AsSizeT:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000293 return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000294 case LengthModifier::AsPtrDiff:
Alexander Shaposhnikov195b25c2017-09-28 23:11:31 +0000295 return ArgType::PtrTo(
296 ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
Ted Kremenek6fa57272012-01-24 21:29:54 +0000297 case LengthModifier::AsLongDouble:
298 // GNU extension.
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000299 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
300 case LengthModifier::AsAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000301 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000302 case LengthModifier::AsInt32:
303 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000304 case LengthModifier::AsWide:
Matt Arsenault58fc8082019-01-29 20:49:54 +0000305 case LengthModifier::AsShortLong:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000306 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000307 }
Matt Arsenault58fc8082019-01-29 20:49:54 +0000308 llvm_unreachable("Unsupported LengthModifier Type");
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000309
310 // Float.
311 case ConversionSpecifier::aArg:
312 case ConversionSpecifier::AArg:
313 case ConversionSpecifier::eArg:
314 case ConversionSpecifier::EArg:
315 case ConversionSpecifier::fArg:
316 case ConversionSpecifier::FArg:
317 case ConversionSpecifier::gArg:
318 case ConversionSpecifier::GArg:
319 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000320 case LengthModifier::None:
321 return ArgType::PtrTo(Ctx.FloatTy);
322 case LengthModifier::AsLong:
323 return ArgType::PtrTo(Ctx.DoubleTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000324 case LengthModifier::AsLongDouble:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000325 return ArgType::PtrTo(Ctx.LongDoubleTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000326 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000327 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000328 }
329
330 // Char, string and scanlist.
331 case ConversionSpecifier::cArg:
332 case ConversionSpecifier::sArg:
333 case ConversionSpecifier::ScanListArg:
334 switch (LM.getKind()) {
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000335 case LengthModifier::None:
336 return ArgType::PtrTo(ArgType::AnyCharTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000337 case LengthModifier::AsLong:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000338 case LengthModifier::AsWide:
Hans Wennborg0d81e012013-05-10 10:08:40 +0000339 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg6073e312012-01-12 17:11:12 +0000340 case LengthModifier::AsAllocate:
341 case LengthModifier::AsMAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000342 return ArgType::PtrTo(ArgType::CStrTy);
Hans Wennborg1b231582014-09-04 21:39:52 +0000343 case LengthModifier::AsShort:
344 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
345 return ArgType::PtrTo(ArgType::AnyCharTy);
Galina Kistanovade7e2212017-06-03 06:23:51 +0000346 LLVM_FALLTHROUGH;
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000347 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000348 return ArgType::Invalid();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000349 }
350 case ConversionSpecifier::CArg:
351 case ConversionSpecifier::SArg:
352 // FIXME: Mac OS X specific?
Hans Wennborg6073e312012-01-12 17:11:12 +0000353 switch (LM.getKind()) {
354 case LengthModifier::None:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000355 case LengthModifier::AsWide:
Hans Wennborg0d81e012013-05-10 10:08:40 +0000356 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
Hans Wennborg6073e312012-01-12 17:11:12 +0000357 case LengthModifier::AsAllocate:
358 case LengthModifier::AsMAllocate:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000359 return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
Hans Wennborg1b231582014-09-04 21:39:52 +0000360 case LengthModifier::AsShort:
361 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
362 return ArgType::PtrTo(ArgType::AnyCharTy);
Galina Kistanovade7e2212017-06-03 06:23:51 +0000363 LLVM_FALLTHROUGH;
Hans Wennborg6073e312012-01-12 17:11:12 +0000364 default:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000365 return ArgType::Invalid();
Hans Wennborg6073e312012-01-12 17:11:12 +0000366 }
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000367
368 // Pointer.
369 case ConversionSpecifier::pArg:
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000370 return ArgType::PtrTo(ArgType::CPointerTy);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000371
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000372 // Write-back.
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000373 case ConversionSpecifier::nArg:
Hans Wennborgabc1e222012-08-07 09:13:19 +0000374 switch (LM.getKind()) {
375 case LengthModifier::None:
376 return ArgType::PtrTo(Ctx.IntTy);
377 case LengthModifier::AsChar:
378 return ArgType::PtrTo(Ctx.SignedCharTy);
379 case LengthModifier::AsShort:
380 return ArgType::PtrTo(Ctx.ShortTy);
381 case LengthModifier::AsLong:
382 return ArgType::PtrTo(Ctx.LongTy);
383 case LengthModifier::AsLongLong:
384 case LengthModifier::AsQuad:
385 return ArgType::PtrTo(Ctx.LongLongTy);
David Majnemer3cba4952013-08-21 21:54:46 +0000386 case LengthModifier::AsInt64:
387 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
Hans Wennborgabc1e222012-08-07 09:13:19 +0000388 case LengthModifier::AsIntMax:
389 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
390 case LengthModifier::AsSizeT:
Alexander Shaposhnikov593e4bb2017-07-20 20:11:47 +0000391 return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
Hans Wennborgabc1e222012-08-07 09:13:19 +0000392 case LengthModifier::AsPtrDiff:
393 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
394 case LengthModifier::AsLongDouble:
395 return ArgType(); // FIXME: Is this a known extension?
396 case LengthModifier::AsAllocate:
397 case LengthModifier::AsMAllocate:
David Majnemer3cba4952013-08-21 21:54:46 +0000398 case LengthModifier::AsInt32:
399 case LengthModifier::AsInt3264:
Hans Wennborg68f42b92014-09-04 21:39:46 +0000400 case LengthModifier::AsWide:
Matt Arsenault58fc8082019-01-29 20:49:54 +0000401 case LengthModifier::AsShortLong:
Hans Wennborgabc1e222012-08-07 09:13:19 +0000402 return ArgType::Invalid();
403 }
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000404
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000405 default:
406 break;
407 }
408
Hans Wennborgb1ab2a82012-08-07 08:59:46 +0000409 return ArgType();
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000410}
411
Jordan Rose177b0a32014-03-20 03:32:39 +0000412bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
413 const LangOptions &LangOpt,
Hans Wennborgd99d6882012-02-15 09:59:46 +0000414 ASTContext &Ctx) {
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000415
Hans Wennborgebcd1c72012-07-30 17:11:32 +0000416 // %n is different from other conversion specifiers; don't try to fix it.
417 if (CS.getKind() == ConversionSpecifier::nArg)
418 return false;
419
Jordan Rose177b0a32014-03-20 03:32:39 +0000420 if (!QT->isPointerType())
421 return false;
422
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000423 QualType PT = QT->getPointeeType();
Jordan Rose614e72b2012-06-04 22:49:02 +0000424
425 // If it's an enum, get its underlying type.
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000426 if (const EnumType *ETy = PT->getAs<EnumType>()) {
427 // Don't try to fix incomplete enums.
428 if (!ETy->getDecl()->isComplete())
429 return false;
Jordan Rose177b0a32014-03-20 03:32:39 +0000430 PT = ETy->getDecl()->getIntegerType();
Benjamin Kramerf3b323d2016-08-20 16:51:33 +0000431 }
Jordan Rose177b0a32014-03-20 03:32:39 +0000432
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000433 const BuiltinType *BT = PT->getAs<BuiltinType>();
434 if (!BT)
435 return false;
436
437 // Pointer to a character.
438 if (PT->isAnyCharacterType()) {
439 CS.setKind(ConversionSpecifier::sArg);
440 if (PT->isWideCharType())
441 LM.setKind(LengthModifier::AsWideChar);
442 else
443 LM.setKind(LengthModifier::None);
Jordan Rose177b0a32014-03-20 03:32:39 +0000444
445 // If we know the target array length, we can use it as a field width.
446 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
447 if (CAT->getSizeModifier() == ArrayType::Normal)
448 FieldWidth = OptionalAmount(OptionalAmount::Constant,
449 CAT->getSize().getZExtValue() - 1,
450 "", 0, false);
451
452 }
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000453 return true;
454 }
455
456 // Figure out the length modifier.
457 switch (BT->getKind()) {
458 // no modifier
459 case BuiltinType::UInt:
460 case BuiltinType::Int:
461 case BuiltinType::Float:
462 LM.setKind(LengthModifier::None);
463 break;
464
465 // hh
466 case BuiltinType::Char_U:
467 case BuiltinType::UChar:
468 case BuiltinType::Char_S:
469 case BuiltinType::SChar:
470 LM.setKind(LengthModifier::AsChar);
471 break;
472
473 // h
474 case BuiltinType::Short:
475 case BuiltinType::UShort:
476 LM.setKind(LengthModifier::AsShort);
477 break;
478
479 // l
480 case BuiltinType::Long:
481 case BuiltinType::ULong:
482 case BuiltinType::Double:
483 LM.setKind(LengthModifier::AsLong);
484 break;
485
486 // ll
487 case BuiltinType::LongLong:
488 case BuiltinType::ULongLong:
489 LM.setKind(LengthModifier::AsLongLong);
490 break;
491
492 // L
493 case BuiltinType::LongDouble:
494 LM.setKind(LengthModifier::AsLongDouble);
495 break;
496
497 // Don't know.
498 default:
499 return false;
500 }
501
502 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
Richard Smith2bf7fdb2013-01-02 11:42:31 +0000503 if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
Hans Wennborg08574d32012-07-27 19:17:46 +0000504 namedTypeToLengthModifier(PT, LM);
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000505
Hans Wennborgd99d6882012-02-15 09:59:46 +0000506 // If fixing the length modifier was enough, we are done.
Matt Arsenault58fc8082019-01-29 20:49:54 +0000507 if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
Jordan Rose92303592012-09-08 04:00:03 +0000508 const analyze_scanf::ArgType &AT = getArgType(Ctx);
509 if (AT.isValid() && AT.matchesType(Ctx, QT))
510 return true;
511 }
Hans Wennborgd99d6882012-02-15 09:59:46 +0000512
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000513 // Figure out the conversion specifier.
514 if (PT->isRealFloatingType())
515 CS.setKind(ConversionSpecifier::fArg);
516 else if (PT->isSignedIntegerType())
517 CS.setKind(ConversionSpecifier::dArg);
Hans Wennborgd99d6882012-02-15 09:59:46 +0000518 else if (PT->isUnsignedIntegerType())
519 CS.setKind(ConversionSpecifier::uArg);
520 else
Hans Wennborgb1a5e092011-12-10 13:20:11 +0000521 llvm_unreachable("Unexpected type");
522
523 return true;
524}
525
526void ScanfSpecifier::toString(raw_ostream &os) const {
527 os << "%";
528
529 if (usesPositionalArg())
530 os << getPositionalArgIndex() << "$";
531 if (SuppressAssignment)
532 os << "*";
533
534 FieldWidth.toString(os);
535 os << LM.toString();
536 os << CS.toString();
537}
538
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000539bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
540 const char *I,
Hans Wennborg23926bd2011-12-15 10:25:47 +0000541 const char *E,
Jordan Rose510260c2012-09-13 02:11:03 +0000542 const LangOptions &LO,
543 const TargetInfo &Target) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000544
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000545 unsigned argIndex = 0;
Fangrui Song6907ce22018-07-30 19:24:48 +0000546
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000547 // Keep looking for a format specifier until we have exhausted the string.
548 while (I != E) {
Hans Wennborg23926bd2011-12-15 10:25:47 +0000549 const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
Jordan Rose510260c2012-09-13 02:11:03 +0000550 LO, Target);
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000551 // Did a fail-stop error of any kind occur when parsing the specifier?
552 // If so, don't do any more processing.
553 if (FSR.shouldStop())
Dmitri Gribenko76bb5cabfa2012-09-10 21:20:09 +0000554 return true;
Ted Kremeneka1ef09402010-07-16 02:11:31 +0000555 // Did we exhaust the string or encounter an error that
556 // we can recover from?
557 if (!FSR.hasValue())
558 continue;
559 // We have a format specifier. Pass it to the callback.
560 if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
561 I - FSR.getStart())) {
562 return true;
563 }
564 }
565 assert(I == E && "Format string not exhausted");
566 return false;
567}