1 //= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
15 #include "clang/Analysis/Analyses/FormatString.h"
16 #include "FormatStringParsing.h"
17 #include "clang/Basic/TargetInfo.h"
19 using clang::analyze_format_string::ArgType;
20 using clang::analyze_format_string::FormatStringHandler;
21 using clang::analyze_format_string::LengthModifier;
22 using clang::analyze_format_string::OptionalAmount;
23 using clang::analyze_format_string::ConversionSpecifier;
24 using clang::analyze_scanf::ScanfConversionSpecifier;
25 using clang::analyze_scanf::ScanfSpecifier;
26 using clang::UpdateOnReturn;
27 using namespace clang;
29 typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
32 static bool ParseScanList(FormatStringHandler &H,
33 ScanfConversionSpecifier &CS,
34 const char *&Beg, const char *E) {
36 const char *start = I - 1;
37 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
39 // No more characters?
41 H.HandleIncompleteScanList(start, I);
45 // Special case: ']' is the first character.
48 H.HandleIncompleteScanList(start, I - 1);
53 // Special case: "^]" are the first characters.
54 if (I + 1 != E && I[0] == '^' && I[1] == ']') {
57 H.HandleIncompleteScanList(start, I - 1);
62 // Look for a ']' character which denotes the end of the scan list.
65 H.HandleIncompleteScanList(start, I - 1);
74 // FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
75 // We can possibly refactor.
76 static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
80 const LangOptions &LO,
81 const TargetInfo &Target) {
82 using namespace clang::analyze_format_string;
83 using namespace clang::analyze_scanf;
85 const char *Start = nullptr;
86 UpdateOnReturn <const char*> UpdateBeg(Beg, I);
88 // Look for a '%' character that indicates the start of a format specifier.
89 for ( ; I != E ; ++I) {
92 // Detect spurious null characters, which are likely errors.
97 Start = I++; // Record the start of the format specifier.
102 // No format specifier found?
107 // No more characters left?
108 H.HandleIncompleteSpecifier(Start, E - Start);
113 if (ParseArgPosition(H, FS, Start, I, E))
117 // No more characters left?
118 H.HandleIncompleteSpecifier(Start, E - Start);
122 // Look for '*' flag if it is present.
124 FS.setSuppressAssignment(I);
126 H.HandleIncompleteSpecifier(Start, E - Start);
131 // 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);
139 // No more characters left?
140 H.HandleIncompleteSpecifier(Start, E - Start);
145 // Look for the length modifier.
146 if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) {
147 // No more characters left?
148 H.HandleIncompleteSpecifier(Start, E - Start);
152 // Detect spurious null characters, which are likely errors.
158 // Finally, look for the conversion specifier.
159 const char *conversionPosition = I++;
160 ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
161 switch (*conversionPosition) {
164 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;
189 if (Target.getTriple().isOSDarwin())
190 k = ConversionSpecifier::DArg;
193 if (Target.getTriple().isOSDarwin())
194 k = ConversionSpecifier::OArg;
197 if (Target.getTriple().isOSDarwin())
198 k = ConversionSpecifier::UArg;
201 ScanfConversionSpecifier CS(conversionPosition, k);
202 if (k == ScanfConversionSpecifier::ScanListArg) {
203 if (ParseScanList(H, CS, I, E))
206 FS.setConversionSpecifier(CS);
207 if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
208 && !FS.usesPositionalArg())
209 FS.setArgIndex(argIndex++);
211 // FIXME: '%' and '*' doesn't make sense. Issue a warning.
212 // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
214 if (k == ScanfConversionSpecifier::InvalidSpecifier) {
215 unsigned Len = I - Beg;
216 if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
217 CS.setEndScanList(Beg + Len);
218 FS.setConversionSpecifier(CS);
220 // Assume the conversion takes one argument.
221 return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
223 return ScanfSpecifierResult(Start, FS);
226 ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
227 const ScanfConversionSpecifier &CS = getConversionSpecifier();
229 if (!CS.consumesDataArgument())
230 return ArgType::Invalid();
232 switch(CS.getKind()) {
234 case ConversionSpecifier::dArg:
235 case ConversionSpecifier::DArg:
236 case ConversionSpecifier::iArg:
237 switch (LM.getKind()) {
238 case LengthModifier::None:
239 return ArgType::PtrTo(Ctx.IntTy);
240 case LengthModifier::AsChar:
241 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);
246 case LengthModifier::AsLongLong:
247 case LengthModifier::AsQuad:
248 return ArgType::PtrTo(Ctx.LongLongTy);
249 case LengthModifier::AsInt64:
250 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
251 case LengthModifier::AsIntMax:
252 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
253 case LengthModifier::AsSizeT:
256 case LengthModifier::AsPtrDiff:
257 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
258 case LengthModifier::AsLongDouble:
260 return ArgType::PtrTo(Ctx.LongLongTy);
261 case LengthModifier::AsAllocate:
262 case LengthModifier::AsMAllocate:
263 case LengthModifier::AsInt32:
264 case LengthModifier::AsInt3264:
265 case LengthModifier::AsWide:
266 return ArgType::Invalid();
270 case ConversionSpecifier::oArg:
271 case ConversionSpecifier::OArg:
272 case ConversionSpecifier::uArg:
273 case ConversionSpecifier::UArg:
274 case ConversionSpecifier::xArg:
275 case ConversionSpecifier::XArg:
276 switch (LM.getKind()) {
277 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);
285 case LengthModifier::AsLongLong:
286 case LengthModifier::AsQuad:
287 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
288 case LengthModifier::AsInt64:
289 return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
290 case LengthModifier::AsIntMax:
291 return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
292 case LengthModifier::AsSizeT:
293 return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
294 case LengthModifier::AsPtrDiff:
295 // FIXME: Unsigned version of ptrdiff_t?
297 case LengthModifier::AsLongDouble:
299 return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
300 case LengthModifier::AsAllocate:
301 case LengthModifier::AsMAllocate:
302 case LengthModifier::AsInt32:
303 case LengthModifier::AsInt3264:
304 case LengthModifier::AsWide:
305 return ArgType::Invalid();
309 case ConversionSpecifier::aArg:
310 case ConversionSpecifier::AArg:
311 case ConversionSpecifier::eArg:
312 case ConversionSpecifier::EArg:
313 case ConversionSpecifier::fArg:
314 case ConversionSpecifier::FArg:
315 case ConversionSpecifier::gArg:
316 case ConversionSpecifier::GArg:
317 switch (LM.getKind()) {
318 case LengthModifier::None:
319 return ArgType::PtrTo(Ctx.FloatTy);
320 case LengthModifier::AsLong:
321 return ArgType::PtrTo(Ctx.DoubleTy);
322 case LengthModifier::AsLongDouble:
323 return ArgType::PtrTo(Ctx.LongDoubleTy);
325 return ArgType::Invalid();
328 // Char, string and scanlist.
329 case ConversionSpecifier::cArg:
330 case ConversionSpecifier::sArg:
331 case ConversionSpecifier::ScanListArg:
332 switch (LM.getKind()) {
333 case LengthModifier::None:
334 return ArgType::PtrTo(ArgType::AnyCharTy);
335 case LengthModifier::AsLong:
336 case LengthModifier::AsWide:
337 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
338 case LengthModifier::AsAllocate:
339 case LengthModifier::AsMAllocate:
340 return ArgType::PtrTo(ArgType::CStrTy);
341 case LengthModifier::AsShort:
342 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
343 return ArgType::PtrTo(ArgType::AnyCharTy);
345 return ArgType::Invalid();
347 case ConversionSpecifier::CArg:
348 case ConversionSpecifier::SArg:
349 // FIXME: Mac OS X specific?
350 switch (LM.getKind()) {
351 case LengthModifier::None:
352 case LengthModifier::AsWide:
353 return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
354 case LengthModifier::AsAllocate:
355 case LengthModifier::AsMAllocate:
356 return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
357 case LengthModifier::AsShort:
358 if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
359 return ArgType::PtrTo(ArgType::AnyCharTy);
361 return ArgType::Invalid();
365 case ConversionSpecifier::pArg:
366 return ArgType::PtrTo(ArgType::CPointerTy);
369 case ConversionSpecifier::nArg:
370 switch (LM.getKind()) {
371 case LengthModifier::None:
372 return ArgType::PtrTo(Ctx.IntTy);
373 case LengthModifier::AsChar:
374 return ArgType::PtrTo(Ctx.SignedCharTy);
375 case LengthModifier::AsShort:
376 return ArgType::PtrTo(Ctx.ShortTy);
377 case LengthModifier::AsLong:
378 return ArgType::PtrTo(Ctx.LongTy);
379 case LengthModifier::AsLongLong:
380 case LengthModifier::AsQuad:
381 return ArgType::PtrTo(Ctx.LongLongTy);
382 case LengthModifier::AsInt64:
383 return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
384 case LengthModifier::AsIntMax:
385 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
386 case LengthModifier::AsSizeT:
387 return ArgType(); // FIXME: ssize_t
388 case LengthModifier::AsPtrDiff:
389 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
390 case LengthModifier::AsLongDouble:
391 return ArgType(); // FIXME: Is this a known extension?
392 case LengthModifier::AsAllocate:
393 case LengthModifier::AsMAllocate:
394 case LengthModifier::AsInt32:
395 case LengthModifier::AsInt3264:
396 case LengthModifier::AsWide:
397 return ArgType::Invalid();
407 bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
408 const LangOptions &LangOpt,
411 // %n is different from other conversion specifiers; don't try to fix it.
412 if (CS.getKind() == ConversionSpecifier::nArg)
415 if (!QT->isPointerType())
418 QualType PT = QT->getPointeeType();
420 // If it's an enum, get its underlying type.
421 if (const EnumType *ETy = PT->getAs<EnumType>()) {
422 // Don't try to fix incomplete enums.
423 if (!ETy->getDecl()->isComplete())
425 PT = ETy->getDecl()->getIntegerType();
428 const BuiltinType *BT = PT->getAs<BuiltinType>();
432 // Pointer to a character.
433 if (PT->isAnyCharacterType()) {
434 CS.setKind(ConversionSpecifier::sArg);
435 if (PT->isWideCharType())
436 LM.setKind(LengthModifier::AsWideChar);
438 LM.setKind(LengthModifier::None);
440 // If we know the target array length, we can use it as a field width.
441 if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
442 if (CAT->getSizeModifier() == ArrayType::Normal)
443 FieldWidth = OptionalAmount(OptionalAmount::Constant,
444 CAT->getSize().getZExtValue() - 1,
451 // Figure out the length modifier.
452 switch (BT->getKind()) {
454 case BuiltinType::UInt:
455 case BuiltinType::Int:
456 case BuiltinType::Float:
457 LM.setKind(LengthModifier::None);
461 case BuiltinType::Char_U:
462 case BuiltinType::UChar:
463 case BuiltinType::Char_S:
464 case BuiltinType::SChar:
465 LM.setKind(LengthModifier::AsChar);
469 case BuiltinType::Short:
470 case BuiltinType::UShort:
471 LM.setKind(LengthModifier::AsShort);
475 case BuiltinType::Long:
476 case BuiltinType::ULong:
477 case BuiltinType::Double:
478 LM.setKind(LengthModifier::AsLong);
482 case BuiltinType::LongLong:
483 case BuiltinType::ULongLong:
484 LM.setKind(LengthModifier::AsLongLong);
488 case BuiltinType::LongDouble:
489 LM.setKind(LengthModifier::AsLongDouble);
497 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
498 if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
499 namedTypeToLengthModifier(PT, LM);
501 // If fixing the length modifier was enough, we are done.
502 if (hasValidLengthModifier(Ctx.getTargetInfo())) {
503 const analyze_scanf::ArgType &AT = getArgType(Ctx);
504 if (AT.isValid() && AT.matchesType(Ctx, QT))
508 // Figure out the conversion specifier.
509 if (PT->isRealFloatingType())
510 CS.setKind(ConversionSpecifier::fArg);
511 else if (PT->isSignedIntegerType())
512 CS.setKind(ConversionSpecifier::dArg);
513 else if (PT->isUnsignedIntegerType())
514 CS.setKind(ConversionSpecifier::uArg);
516 llvm_unreachable("Unexpected type");
521 void ScanfSpecifier::toString(raw_ostream &os) const {
524 if (usesPositionalArg())
525 os << getPositionalArgIndex() << "$";
526 if (SuppressAssignment)
529 FieldWidth.toString(os);
534 bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
537 const LangOptions &LO,
538 const TargetInfo &Target) {
540 unsigned argIndex = 0;
542 // Keep looking for a format specifier until we have exhausted the string.
544 const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
546 // Did a fail-stop error of any kind occur when parsing the specifier?
547 // If so, don't do any more processing.
548 if (FSR.shouldStop())
550 // Did we exhaust the string or encounter an error that
551 // we can recover from?
554 // We have a format specifier. Pass it to the callback.
555 if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
556 I - FSR.getStart())) {
560 assert(I == E && "Format string not exhausted");