13d1dcd9bSDimitry Andric //= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
23d1dcd9bSDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d1dcd9bSDimitry Andric //
73d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
83d1dcd9bSDimitry Andric //
93d1dcd9bSDimitry Andric // Handling of format string in scanf and friends. The structure of format
103d1dcd9bSDimitry Andric // strings for fscanf() are described in C99 7.19.6.2.
113d1dcd9bSDimitry Andric //
123d1dcd9bSDimitry Andric //===----------------------------------------------------------------------===//
133d1dcd9bSDimitry Andric
14676fbe81SDimitry Andric #include "clang/AST/FormatString.h"
153d1dcd9bSDimitry Andric #include "FormatStringParsing.h"
16809500fcSDimitry Andric #include "clang/Basic/TargetInfo.h"
173d1dcd9bSDimitry Andric
1856d91b49SDimitry Andric using clang::analyze_format_string::ArgType;
193d1dcd9bSDimitry Andric using clang::analyze_format_string::FormatStringHandler;
203d1dcd9bSDimitry Andric using clang::analyze_format_string::LengthModifier;
213d1dcd9bSDimitry Andric using clang::analyze_format_string::OptionalAmount;
223d1dcd9bSDimitry Andric using clang::analyze_format_string::ConversionSpecifier;
233d1dcd9bSDimitry Andric using clang::analyze_scanf::ScanfConversionSpecifier;
243d1dcd9bSDimitry Andric using clang::analyze_scanf::ScanfSpecifier;
253d1dcd9bSDimitry Andric using clang::UpdateOnReturn;
26dbe13110SDimitry Andric using namespace clang;
273d1dcd9bSDimitry Andric
283d1dcd9bSDimitry Andric typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
293d1dcd9bSDimitry Andric ScanfSpecifierResult;
303d1dcd9bSDimitry Andric
ParseScanList(FormatStringHandler & H,ScanfConversionSpecifier & CS,const char * & Beg,const char * E)313d1dcd9bSDimitry Andric static bool ParseScanList(FormatStringHandler &H,
323d1dcd9bSDimitry Andric ScanfConversionSpecifier &CS,
333d1dcd9bSDimitry Andric const char *&Beg, const char *E) {
343d1dcd9bSDimitry Andric const char *I = Beg;
353d1dcd9bSDimitry Andric const char *start = I - 1;
363d1dcd9bSDimitry Andric UpdateOnReturn <const char*> UpdateBeg(Beg, I);
373d1dcd9bSDimitry Andric
383d1dcd9bSDimitry Andric // No more characters?
393d1dcd9bSDimitry Andric if (I == E) {
403d1dcd9bSDimitry Andric H.HandleIncompleteScanList(start, I);
413d1dcd9bSDimitry Andric return true;
423d1dcd9bSDimitry Andric }
433d1dcd9bSDimitry Andric
443d1dcd9bSDimitry Andric // Special case: ']' is the first character.
453d1dcd9bSDimitry Andric if (*I == ']') {
463d1dcd9bSDimitry Andric if (++I == E) {
473d1dcd9bSDimitry Andric H.HandleIncompleteScanList(start, I - 1);
483d1dcd9bSDimitry Andric return true;
493d1dcd9bSDimitry Andric }
503d1dcd9bSDimitry Andric }
513d1dcd9bSDimitry Andric
529f4dbff6SDimitry Andric // Special case: "^]" are the first characters.
539f4dbff6SDimitry Andric if (I + 1 != E && I[0] == '^' && I[1] == ']') {
549f4dbff6SDimitry Andric I += 2;
559f4dbff6SDimitry Andric if (I == E) {
569f4dbff6SDimitry Andric H.HandleIncompleteScanList(start, I - 1);
579f4dbff6SDimitry Andric return true;
589f4dbff6SDimitry Andric }
599f4dbff6SDimitry Andric }
609f4dbff6SDimitry Andric
613d1dcd9bSDimitry Andric // Look for a ']' character which denotes the end of the scan list.
623d1dcd9bSDimitry Andric while (*I != ']') {
633d1dcd9bSDimitry Andric if (++I == E) {
643d1dcd9bSDimitry Andric H.HandleIncompleteScanList(start, I - 1);
653d1dcd9bSDimitry Andric return true;
663d1dcd9bSDimitry Andric }
673d1dcd9bSDimitry Andric }
683d1dcd9bSDimitry Andric
693d1dcd9bSDimitry Andric CS.setEndScanList(I);
703d1dcd9bSDimitry Andric return false;
713d1dcd9bSDimitry Andric }
723d1dcd9bSDimitry Andric
733d1dcd9bSDimitry Andric // FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
743d1dcd9bSDimitry Andric // We can possibly refactor.
ParseScanfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target)753d1dcd9bSDimitry Andric static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
763d1dcd9bSDimitry Andric const char *&Beg,
773d1dcd9bSDimitry Andric const char *E,
78dbe13110SDimitry Andric unsigned &argIndex,
7913cc256eSDimitry Andric const LangOptions &LO,
8013cc256eSDimitry Andric const TargetInfo &Target) {
812b6b257fSDimitry Andric using namespace clang::analyze_format_string;
823d1dcd9bSDimitry Andric using namespace clang::analyze_scanf;
833d1dcd9bSDimitry Andric const char *I = Beg;
849f4dbff6SDimitry Andric const char *Start = nullptr;
853d1dcd9bSDimitry Andric UpdateOnReturn <const char*> UpdateBeg(Beg, I);
863d1dcd9bSDimitry Andric
873d1dcd9bSDimitry Andric // Look for a '%' character that indicates the start of a format specifier.
883d1dcd9bSDimitry Andric for ( ; I != E ; ++I) {
893d1dcd9bSDimitry Andric char c = *I;
903d1dcd9bSDimitry Andric if (c == '\0') {
913d1dcd9bSDimitry Andric // Detect spurious null characters, which are likely errors.
923d1dcd9bSDimitry Andric H.HandleNullChar(I);
933d1dcd9bSDimitry Andric return true;
943d1dcd9bSDimitry Andric }
953d1dcd9bSDimitry Andric if (c == '%') {
963d1dcd9bSDimitry Andric Start = I++; // Record the start of the format specifier.
973d1dcd9bSDimitry Andric break;
983d1dcd9bSDimitry Andric }
993d1dcd9bSDimitry Andric }
1003d1dcd9bSDimitry Andric
1013d1dcd9bSDimitry Andric // No format specifier found?
1023d1dcd9bSDimitry Andric if (!Start)
1033d1dcd9bSDimitry Andric return false;
1043d1dcd9bSDimitry Andric
1053d1dcd9bSDimitry Andric if (I == E) {
1063d1dcd9bSDimitry Andric // No more characters left?
1073d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1083d1dcd9bSDimitry Andric return true;
1093d1dcd9bSDimitry Andric }
1103d1dcd9bSDimitry Andric
1113d1dcd9bSDimitry Andric ScanfSpecifier FS;
1123d1dcd9bSDimitry Andric if (ParseArgPosition(H, FS, Start, I, E))
1133d1dcd9bSDimitry Andric return true;
1143d1dcd9bSDimitry Andric
1153d1dcd9bSDimitry Andric if (I == E) {
1163d1dcd9bSDimitry Andric // No more characters left?
1173d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1183d1dcd9bSDimitry Andric return true;
1193d1dcd9bSDimitry Andric }
1203d1dcd9bSDimitry Andric
1213d1dcd9bSDimitry Andric // Look for '*' flag if it is present.
1223d1dcd9bSDimitry Andric if (*I == '*') {
1233d1dcd9bSDimitry Andric FS.setSuppressAssignment(I);
1243d1dcd9bSDimitry Andric if (++I == E) {
1253d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1263d1dcd9bSDimitry Andric return true;
1273d1dcd9bSDimitry Andric }
1283d1dcd9bSDimitry Andric }
1293d1dcd9bSDimitry Andric
1303d1dcd9bSDimitry Andric // Look for the field width (if any). Unlike printf, this is either
1313d1dcd9bSDimitry Andric // a fixed integer or isn't present.
1323d1dcd9bSDimitry Andric const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
1333d1dcd9bSDimitry Andric if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
1343d1dcd9bSDimitry Andric assert(Amt.getHowSpecified() == OptionalAmount::Constant);
1353d1dcd9bSDimitry Andric FS.setFieldWidth(Amt);
1363d1dcd9bSDimitry Andric
1373d1dcd9bSDimitry Andric if (I == E) {
1383d1dcd9bSDimitry Andric // No more characters left?
1393d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1403d1dcd9bSDimitry Andric return true;
1413d1dcd9bSDimitry Andric }
1423d1dcd9bSDimitry Andric }
1433d1dcd9bSDimitry Andric
1443d1dcd9bSDimitry Andric // Look for the length modifier.
14522989816SDimitry Andric if (ParseLengthModifier(FS, I, E, LO, /*IsScanf=*/true) && I == E) {
1463d1dcd9bSDimitry Andric // No more characters left?
1473d1dcd9bSDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start);
1483d1dcd9bSDimitry Andric return true;
1493d1dcd9bSDimitry Andric }
1503d1dcd9bSDimitry Andric
1513d1dcd9bSDimitry Andric // Detect spurious null characters, which are likely errors.
1523d1dcd9bSDimitry Andric if (*I == '\0') {
1533d1dcd9bSDimitry Andric H.HandleNullChar(I);
1543d1dcd9bSDimitry Andric return true;
1553d1dcd9bSDimitry Andric }
1563d1dcd9bSDimitry Andric
1573d1dcd9bSDimitry Andric // Finally, look for the conversion specifier.
1583d1dcd9bSDimitry Andric const char *conversionPosition = I++;
1593d1dcd9bSDimitry Andric ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
1603d1dcd9bSDimitry Andric switch (*conversionPosition) {
1613d1dcd9bSDimitry Andric default:
1623d1dcd9bSDimitry Andric break;
1633d1dcd9bSDimitry Andric case '%': k = ConversionSpecifier::PercentArg; break;
164e3b55780SDimitry Andric case 'b': k = ConversionSpecifier::bArg; break;
1653d1dcd9bSDimitry Andric case 'A': k = ConversionSpecifier::AArg; break;
1663d1dcd9bSDimitry Andric case 'E': k = ConversionSpecifier::EArg; break;
1673d1dcd9bSDimitry Andric case 'F': k = ConversionSpecifier::FArg; break;
1683d1dcd9bSDimitry Andric case 'G': k = ConversionSpecifier::GArg; break;
1693d1dcd9bSDimitry Andric case 'X': k = ConversionSpecifier::XArg; break;
1703d1dcd9bSDimitry Andric case 'a': k = ConversionSpecifier::aArg; break;
1713d1dcd9bSDimitry Andric case 'd': k = ConversionSpecifier::dArg; break;
1723d1dcd9bSDimitry Andric case 'e': k = ConversionSpecifier::eArg; break;
1733d1dcd9bSDimitry Andric case 'f': k = ConversionSpecifier::fArg; break;
1743d1dcd9bSDimitry Andric case 'g': k = ConversionSpecifier::gArg; break;
1753d1dcd9bSDimitry Andric case 'i': k = ConversionSpecifier::iArg; break;
1763d1dcd9bSDimitry Andric case 'n': k = ConversionSpecifier::nArg; break;
1773d1dcd9bSDimitry Andric case 'c': k = ConversionSpecifier::cArg; break;
1783d1dcd9bSDimitry Andric case 'C': k = ConversionSpecifier::CArg; break;
1793d1dcd9bSDimitry Andric case 'S': k = ConversionSpecifier::SArg; break;
1803d1dcd9bSDimitry Andric case '[': k = ConversionSpecifier::ScanListArg; break;
1813d1dcd9bSDimitry Andric case 'u': k = ConversionSpecifier::uArg; break;
1823d1dcd9bSDimitry Andric case 'x': k = ConversionSpecifier::xArg; break;
1833d1dcd9bSDimitry Andric case 'o': k = ConversionSpecifier::oArg; break;
1843d1dcd9bSDimitry Andric case 's': k = ConversionSpecifier::sArg; break;
1853d1dcd9bSDimitry Andric case 'p': k = ConversionSpecifier::pArg; break;
18613cc256eSDimitry Andric // Apple extensions
18713cc256eSDimitry Andric // Apple-specific
18813cc256eSDimitry Andric case 'D':
18913cc256eSDimitry Andric if (Target.getTriple().isOSDarwin())
19013cc256eSDimitry Andric k = ConversionSpecifier::DArg;
19113cc256eSDimitry Andric break;
19213cc256eSDimitry Andric case 'O':
19313cc256eSDimitry Andric if (Target.getTriple().isOSDarwin())
19413cc256eSDimitry Andric k = ConversionSpecifier::OArg;
19513cc256eSDimitry Andric break;
19613cc256eSDimitry Andric case 'U':
19713cc256eSDimitry Andric if (Target.getTriple().isOSDarwin())
19813cc256eSDimitry Andric k = ConversionSpecifier::UArg;
19913cc256eSDimitry Andric break;
2003d1dcd9bSDimitry Andric }
2013d1dcd9bSDimitry Andric ScanfConversionSpecifier CS(conversionPosition, k);
2023d1dcd9bSDimitry Andric if (k == ScanfConversionSpecifier::ScanListArg) {
203dbe13110SDimitry Andric if (ParseScanList(H, CS, I, E))
2043d1dcd9bSDimitry Andric return true;
2053d1dcd9bSDimitry Andric }
2063d1dcd9bSDimitry Andric FS.setConversionSpecifier(CS);
2073d1dcd9bSDimitry Andric if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
2083d1dcd9bSDimitry Andric && !FS.usesPositionalArg())
2093d1dcd9bSDimitry Andric FS.setArgIndex(argIndex++);
2103d1dcd9bSDimitry Andric
2113d1dcd9bSDimitry Andric // FIXME: '%' and '*' doesn't make sense. Issue a warning.
2123d1dcd9bSDimitry Andric // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
2133d1dcd9bSDimitry Andric
2143d1dcd9bSDimitry Andric if (k == ScanfConversionSpecifier::InvalidSpecifier) {
2152b6b257fSDimitry Andric unsigned Len = I - Beg;
2162b6b257fSDimitry Andric if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
2172b6b257fSDimitry Andric CS.setEndScanList(Beg + Len);
2182b6b257fSDimitry Andric FS.setConversionSpecifier(CS);
2192b6b257fSDimitry Andric }
2203d1dcd9bSDimitry Andric // Assume the conversion takes one argument.
2212b6b257fSDimitry Andric return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
2223d1dcd9bSDimitry Andric }
2233d1dcd9bSDimitry Andric return ScanfSpecifierResult(Start, FS);
2243d1dcd9bSDimitry Andric }
2253d1dcd9bSDimitry Andric
getArgType(ASTContext & Ctx) const22656d91b49SDimitry Andric ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
227dbe13110SDimitry Andric const ScanfConversionSpecifier &CS = getConversionSpecifier();
228dbe13110SDimitry Andric
229dbe13110SDimitry Andric if (!CS.consumesDataArgument())
23056d91b49SDimitry Andric return ArgType::Invalid();
231dbe13110SDimitry Andric
232dbe13110SDimitry Andric switch(CS.getKind()) {
233dbe13110SDimitry Andric // Signed int.
234dbe13110SDimitry Andric case ConversionSpecifier::dArg:
23513cc256eSDimitry Andric case ConversionSpecifier::DArg:
236dbe13110SDimitry Andric case ConversionSpecifier::iArg:
237dbe13110SDimitry Andric switch (LM.getKind()) {
23856d91b49SDimitry Andric case LengthModifier::None:
23956d91b49SDimitry Andric return ArgType::PtrTo(Ctx.IntTy);
240dbe13110SDimitry Andric case LengthModifier::AsChar:
24156d91b49SDimitry Andric return ArgType::PtrTo(ArgType::AnyCharTy);
24256d91b49SDimitry Andric case LengthModifier::AsShort:
24356d91b49SDimitry Andric return ArgType::PtrTo(Ctx.ShortTy);
24456d91b49SDimitry Andric case LengthModifier::AsLong:
24556d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongTy);
246dbe13110SDimitry Andric case LengthModifier::AsLongLong:
247dbe13110SDimitry Andric case LengthModifier::AsQuad:
24856d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongLongTy);
249bfef3995SDimitry Andric case LengthModifier::AsInt64:
250bfef3995SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
251dbe13110SDimitry Andric case LengthModifier::AsIntMax:
25256d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
253dbe13110SDimitry Andric case LengthModifier::AsSizeT:
254461a67faSDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
255dbe13110SDimitry Andric case LengthModifier::AsPtrDiff:
25656d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
257dbe13110SDimitry Andric case LengthModifier::AsLongDouble:
258dbe13110SDimitry Andric // GNU extension.
25956d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongLongTy);
26056d91b49SDimitry Andric case LengthModifier::AsAllocate:
26156d91b49SDimitry Andric case LengthModifier::AsMAllocate:
262bfef3995SDimitry Andric case LengthModifier::AsInt32:
263bfef3995SDimitry Andric case LengthModifier::AsInt3264:
26406d4ba38SDimitry Andric case LengthModifier::AsWide:
26522989816SDimitry Andric case LengthModifier::AsShortLong:
26656d91b49SDimitry Andric return ArgType::Invalid();
267dbe13110SDimitry Andric }
26822989816SDimitry Andric llvm_unreachable("Unsupported LengthModifier Type");
269dbe13110SDimitry Andric
270dbe13110SDimitry Andric // Unsigned int.
271e3b55780SDimitry Andric case ConversionSpecifier::bArg:
272dbe13110SDimitry Andric case ConversionSpecifier::oArg:
27313cc256eSDimitry Andric case ConversionSpecifier::OArg:
274dbe13110SDimitry Andric case ConversionSpecifier::uArg:
27513cc256eSDimitry Andric case ConversionSpecifier::UArg:
276dbe13110SDimitry Andric case ConversionSpecifier::xArg:
277dbe13110SDimitry Andric case ConversionSpecifier::XArg:
278dbe13110SDimitry Andric switch (LM.getKind()) {
27956d91b49SDimitry Andric case LengthModifier::None:
28056d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedIntTy);
28156d91b49SDimitry Andric case LengthModifier::AsChar:
28256d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedCharTy);
28356d91b49SDimitry Andric case LengthModifier::AsShort:
28456d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedShortTy);
28556d91b49SDimitry Andric case LengthModifier::AsLong:
28656d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedLongTy);
287dbe13110SDimitry Andric case LengthModifier::AsLongLong:
288dbe13110SDimitry Andric case LengthModifier::AsQuad:
28956d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
290bfef3995SDimitry Andric case LengthModifier::AsInt64:
291bfef3995SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
292dbe13110SDimitry Andric case LengthModifier::AsIntMax:
29356d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
294dbe13110SDimitry Andric case LengthModifier::AsSizeT:
29556d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
296dbe13110SDimitry Andric case LengthModifier::AsPtrDiff:
297461a67faSDimitry Andric return ArgType::PtrTo(
298461a67faSDimitry Andric ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
299dbe13110SDimitry Andric case LengthModifier::AsLongDouble:
300dbe13110SDimitry Andric // GNU extension.
30156d91b49SDimitry Andric return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
30256d91b49SDimitry Andric case LengthModifier::AsAllocate:
30356d91b49SDimitry Andric case LengthModifier::AsMAllocate:
304bfef3995SDimitry Andric case LengthModifier::AsInt32:
305bfef3995SDimitry Andric case LengthModifier::AsInt3264:
30606d4ba38SDimitry Andric case LengthModifier::AsWide:
30722989816SDimitry Andric case LengthModifier::AsShortLong:
30856d91b49SDimitry Andric return ArgType::Invalid();
309dbe13110SDimitry Andric }
31022989816SDimitry Andric llvm_unreachable("Unsupported LengthModifier Type");
311dbe13110SDimitry Andric
312dbe13110SDimitry Andric // Float.
313dbe13110SDimitry Andric case ConversionSpecifier::aArg:
314dbe13110SDimitry Andric case ConversionSpecifier::AArg:
315dbe13110SDimitry Andric case ConversionSpecifier::eArg:
316dbe13110SDimitry Andric case ConversionSpecifier::EArg:
317dbe13110SDimitry Andric case ConversionSpecifier::fArg:
318dbe13110SDimitry Andric case ConversionSpecifier::FArg:
319dbe13110SDimitry Andric case ConversionSpecifier::gArg:
320dbe13110SDimitry Andric case ConversionSpecifier::GArg:
321dbe13110SDimitry Andric switch (LM.getKind()) {
32256d91b49SDimitry Andric case LengthModifier::None:
32356d91b49SDimitry Andric return ArgType::PtrTo(Ctx.FloatTy);
32456d91b49SDimitry Andric case LengthModifier::AsLong:
32556d91b49SDimitry Andric return ArgType::PtrTo(Ctx.DoubleTy);
326dbe13110SDimitry Andric case LengthModifier::AsLongDouble:
32756d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongDoubleTy);
328dbe13110SDimitry Andric default:
32956d91b49SDimitry Andric return ArgType::Invalid();
330dbe13110SDimitry Andric }
331dbe13110SDimitry Andric
332dbe13110SDimitry Andric // Char, string and scanlist.
333dbe13110SDimitry Andric case ConversionSpecifier::cArg:
334dbe13110SDimitry Andric case ConversionSpecifier::sArg:
335dbe13110SDimitry Andric case ConversionSpecifier::ScanListArg:
336dbe13110SDimitry Andric switch (LM.getKind()) {
33756d91b49SDimitry Andric case LengthModifier::None:
33856d91b49SDimitry Andric return ArgType::PtrTo(ArgType::AnyCharTy);
339dbe13110SDimitry Andric case LengthModifier::AsLong:
34006d4ba38SDimitry Andric case LengthModifier::AsWide:
341bfef3995SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
342dbe13110SDimitry Andric case LengthModifier::AsAllocate:
343dbe13110SDimitry Andric case LengthModifier::AsMAllocate:
34456d91b49SDimitry Andric return ArgType::PtrTo(ArgType::CStrTy);
34506d4ba38SDimitry Andric case LengthModifier::AsShort:
34606d4ba38SDimitry Andric if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
34706d4ba38SDimitry Andric return ArgType::PtrTo(ArgType::AnyCharTy);
348e3b55780SDimitry Andric [[fallthrough]];
349dbe13110SDimitry Andric default:
35056d91b49SDimitry Andric return ArgType::Invalid();
351dbe13110SDimitry Andric }
352dbe13110SDimitry Andric case ConversionSpecifier::CArg:
353dbe13110SDimitry Andric case ConversionSpecifier::SArg:
354dbe13110SDimitry Andric // FIXME: Mac OS X specific?
355dbe13110SDimitry Andric switch (LM.getKind()) {
356dbe13110SDimitry Andric case LengthModifier::None:
35706d4ba38SDimitry Andric case LengthModifier::AsWide:
358bfef3995SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
359dbe13110SDimitry Andric case LengthModifier::AsAllocate:
360dbe13110SDimitry Andric case LengthModifier::AsMAllocate:
36156d91b49SDimitry Andric return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
36206d4ba38SDimitry Andric case LengthModifier::AsShort:
36306d4ba38SDimitry Andric if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
36406d4ba38SDimitry Andric return ArgType::PtrTo(ArgType::AnyCharTy);
365e3b55780SDimitry Andric [[fallthrough]];
366dbe13110SDimitry Andric default:
36756d91b49SDimitry Andric return ArgType::Invalid();
368dbe13110SDimitry Andric }
369dbe13110SDimitry Andric
370dbe13110SDimitry Andric // Pointer.
371dbe13110SDimitry Andric case ConversionSpecifier::pArg:
37256d91b49SDimitry Andric return ArgType::PtrTo(ArgType::CPointerTy);
37356d91b49SDimitry Andric
37456d91b49SDimitry Andric // Write-back.
37556d91b49SDimitry Andric case ConversionSpecifier::nArg:
37656d91b49SDimitry Andric switch (LM.getKind()) {
37756d91b49SDimitry Andric case LengthModifier::None:
37856d91b49SDimitry Andric return ArgType::PtrTo(Ctx.IntTy);
37956d91b49SDimitry Andric case LengthModifier::AsChar:
38056d91b49SDimitry Andric return ArgType::PtrTo(Ctx.SignedCharTy);
38156d91b49SDimitry Andric case LengthModifier::AsShort:
38256d91b49SDimitry Andric return ArgType::PtrTo(Ctx.ShortTy);
38356d91b49SDimitry Andric case LengthModifier::AsLong:
38456d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongTy);
38556d91b49SDimitry Andric case LengthModifier::AsLongLong:
38656d91b49SDimitry Andric case LengthModifier::AsQuad:
38756d91b49SDimitry Andric return ArgType::PtrTo(Ctx.LongLongTy);
388bfef3995SDimitry Andric case LengthModifier::AsInt64:
389bfef3995SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
39056d91b49SDimitry Andric case LengthModifier::AsIntMax:
39156d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
39256d91b49SDimitry Andric case LengthModifier::AsSizeT:
393461a67faSDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
39456d91b49SDimitry Andric case LengthModifier::AsPtrDiff:
39556d91b49SDimitry Andric return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
39656d91b49SDimitry Andric case LengthModifier::AsLongDouble:
39756d91b49SDimitry Andric return ArgType(); // FIXME: Is this a known extension?
39856d91b49SDimitry Andric case LengthModifier::AsAllocate:
39956d91b49SDimitry Andric case LengthModifier::AsMAllocate:
400bfef3995SDimitry Andric case LengthModifier::AsInt32:
401bfef3995SDimitry Andric case LengthModifier::AsInt3264:
40206d4ba38SDimitry Andric case LengthModifier::AsWide:
40322989816SDimitry Andric case LengthModifier::AsShortLong:
40456d91b49SDimitry Andric return ArgType::Invalid();
40556d91b49SDimitry Andric }
406dbe13110SDimitry Andric
407dbe13110SDimitry Andric default:
408dbe13110SDimitry Andric break;
409dbe13110SDimitry Andric }
410dbe13110SDimitry Andric
41156d91b49SDimitry Andric return ArgType();
412dbe13110SDimitry Andric }
413dbe13110SDimitry Andric
fixType(QualType QT,QualType RawQT,const LangOptions & LangOpt,ASTContext & Ctx)4149f4dbff6SDimitry Andric bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
4159f4dbff6SDimitry Andric const LangOptions &LangOpt,
416dbe13110SDimitry Andric ASTContext &Ctx) {
417dbe13110SDimitry Andric
41856d91b49SDimitry Andric // %n is different from other conversion specifiers; don't try to fix it.
41956d91b49SDimitry Andric if (CS.getKind() == ConversionSpecifier::nArg)
42056d91b49SDimitry Andric return false;
42156d91b49SDimitry Andric
4229f4dbff6SDimitry Andric if (!QT->isPointerType())
4239f4dbff6SDimitry Andric return false;
4249f4dbff6SDimitry Andric
425dbe13110SDimitry Andric QualType PT = QT->getPointeeType();
42656d91b49SDimitry Andric
42756d91b49SDimitry Andric // If it's an enum, get its underlying type.
428bab175ecSDimitry Andric if (const EnumType *ETy = PT->getAs<EnumType>()) {
429bab175ecSDimitry Andric // Don't try to fix incomplete enums.
430bab175ecSDimitry Andric if (!ETy->getDecl()->isComplete())
431bab175ecSDimitry Andric return false;
4329f4dbff6SDimitry Andric PT = ETy->getDecl()->getIntegerType();
433bab175ecSDimitry Andric }
43456d91b49SDimitry Andric
435dbe13110SDimitry Andric const BuiltinType *BT = PT->getAs<BuiltinType>();
436dbe13110SDimitry Andric if (!BT)
437dbe13110SDimitry Andric return false;
438dbe13110SDimitry Andric
439dbe13110SDimitry Andric // Pointer to a character.
440dbe13110SDimitry Andric if (PT->isAnyCharacterType()) {
441dbe13110SDimitry Andric CS.setKind(ConversionSpecifier::sArg);
442dbe13110SDimitry Andric if (PT->isWideCharType())
443dbe13110SDimitry Andric LM.setKind(LengthModifier::AsWideChar);
444dbe13110SDimitry Andric else
445dbe13110SDimitry Andric LM.setKind(LengthModifier::None);
4469f4dbff6SDimitry Andric
4479f4dbff6SDimitry Andric // If we know the target array length, we can use it as a field width.
4489f4dbff6SDimitry Andric if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
449b1c73532SDimitry Andric if (CAT->getSizeModifier() == ArraySizeModifier::Normal)
4509f4dbff6SDimitry Andric FieldWidth = OptionalAmount(OptionalAmount::Constant,
451ac9a064cSDimitry Andric CAT->getZExtSize() - 1, "", 0, false);
4529f4dbff6SDimitry Andric }
453dbe13110SDimitry Andric return true;
454dbe13110SDimitry Andric }
455dbe13110SDimitry Andric
456dbe13110SDimitry Andric // Figure out the length modifier.
457dbe13110SDimitry Andric switch (BT->getKind()) {
458dbe13110SDimitry Andric // no modifier
459dbe13110SDimitry Andric case BuiltinType::UInt:
460dbe13110SDimitry Andric case BuiltinType::Int:
461dbe13110SDimitry Andric case BuiltinType::Float:
462dbe13110SDimitry Andric LM.setKind(LengthModifier::None);
463dbe13110SDimitry Andric break;
464dbe13110SDimitry Andric
465dbe13110SDimitry Andric // hh
466dbe13110SDimitry Andric case BuiltinType::Char_U:
467dbe13110SDimitry Andric case BuiltinType::UChar:
468dbe13110SDimitry Andric case BuiltinType::Char_S:
469dbe13110SDimitry Andric case BuiltinType::SChar:
470dbe13110SDimitry Andric LM.setKind(LengthModifier::AsChar);
471dbe13110SDimitry Andric break;
472dbe13110SDimitry Andric
473dbe13110SDimitry Andric // h
474dbe13110SDimitry Andric case BuiltinType::Short:
475dbe13110SDimitry Andric case BuiltinType::UShort:
476dbe13110SDimitry Andric LM.setKind(LengthModifier::AsShort);
477dbe13110SDimitry Andric break;
478dbe13110SDimitry Andric
479dbe13110SDimitry Andric // l
480dbe13110SDimitry Andric case BuiltinType::Long:
481dbe13110SDimitry Andric case BuiltinType::ULong:
482dbe13110SDimitry Andric case BuiltinType::Double:
483dbe13110SDimitry Andric LM.setKind(LengthModifier::AsLong);
484dbe13110SDimitry Andric break;
485dbe13110SDimitry Andric
486dbe13110SDimitry Andric // ll
487dbe13110SDimitry Andric case BuiltinType::LongLong:
488dbe13110SDimitry Andric case BuiltinType::ULongLong:
489dbe13110SDimitry Andric LM.setKind(LengthModifier::AsLongLong);
490dbe13110SDimitry Andric break;
491dbe13110SDimitry Andric
492dbe13110SDimitry Andric // L
493dbe13110SDimitry Andric case BuiltinType::LongDouble:
494dbe13110SDimitry Andric LM.setKind(LengthModifier::AsLongDouble);
495dbe13110SDimitry Andric break;
496dbe13110SDimitry Andric
497dbe13110SDimitry Andric // Don't know.
498dbe13110SDimitry Andric default:
499dbe13110SDimitry Andric return false;
500dbe13110SDimitry Andric }
501dbe13110SDimitry Andric
502dbe13110SDimitry Andric // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
503e3b55780SDimitry Andric if (LangOpt.C99 || LangOpt.CPlusPlus11)
50456d91b49SDimitry Andric namedTypeToLengthModifier(PT, LM);
505dbe13110SDimitry Andric
506dbe13110SDimitry Andric // If fixing the length modifier was enough, we are done.
50722989816SDimitry Andric if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
50856d91b49SDimitry Andric const analyze_scanf::ArgType &AT = getArgType(Ctx);
50913cc256eSDimitry Andric if (AT.isValid() && AT.matchesType(Ctx, QT))
510dbe13110SDimitry Andric return true;
51113cc256eSDimitry Andric }
512dbe13110SDimitry Andric
513dbe13110SDimitry Andric // Figure out the conversion specifier.
514dbe13110SDimitry Andric if (PT->isRealFloatingType())
515dbe13110SDimitry Andric CS.setKind(ConversionSpecifier::fArg);
516dbe13110SDimitry Andric else if (PT->isSignedIntegerType())
517dbe13110SDimitry Andric CS.setKind(ConversionSpecifier::dArg);
518dbe13110SDimitry Andric else if (PT->isUnsignedIntegerType())
519dbe13110SDimitry Andric CS.setKind(ConversionSpecifier::uArg);
520dbe13110SDimitry Andric else
521dbe13110SDimitry Andric llvm_unreachable("Unexpected type");
522dbe13110SDimitry Andric
523dbe13110SDimitry Andric return true;
524dbe13110SDimitry Andric }
525dbe13110SDimitry Andric
toString(raw_ostream & os) const526dbe13110SDimitry Andric void ScanfSpecifier::toString(raw_ostream &os) const {
527dbe13110SDimitry Andric os << "%";
528dbe13110SDimitry Andric
529dbe13110SDimitry Andric if (usesPositionalArg())
530dbe13110SDimitry Andric os << getPositionalArgIndex() << "$";
531dbe13110SDimitry Andric if (SuppressAssignment)
532dbe13110SDimitry Andric os << "*";
533dbe13110SDimitry Andric
534dbe13110SDimitry Andric FieldWidth.toString(os);
535dbe13110SDimitry Andric os << LM.toString();
536dbe13110SDimitry Andric os << CS.toString();
537dbe13110SDimitry Andric }
538dbe13110SDimitry Andric
ParseScanfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)5393d1dcd9bSDimitry Andric bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
5403d1dcd9bSDimitry Andric const char *I,
541dbe13110SDimitry Andric const char *E,
54213cc256eSDimitry Andric const LangOptions &LO,
54313cc256eSDimitry Andric const TargetInfo &Target) {
5443d1dcd9bSDimitry Andric
5453d1dcd9bSDimitry Andric unsigned argIndex = 0;
5463d1dcd9bSDimitry Andric
5473d1dcd9bSDimitry Andric // Keep looking for a format specifier until we have exhausted the string.
5483d1dcd9bSDimitry Andric while (I != E) {
549dbe13110SDimitry Andric const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
55013cc256eSDimitry Andric LO, Target);
5513d1dcd9bSDimitry Andric // Did a fail-stop error of any kind occur when parsing the specifier?
5523d1dcd9bSDimitry Andric // If so, don't do any more processing.
5533d1dcd9bSDimitry Andric if (FSR.shouldStop())
55413cc256eSDimitry Andric return true;
5553d1dcd9bSDimitry Andric // Did we exhaust the string or encounter an error that
5563d1dcd9bSDimitry Andric // we can recover from?
5573d1dcd9bSDimitry Andric if (!FSR.hasValue())
5583d1dcd9bSDimitry Andric continue;
5593d1dcd9bSDimitry Andric // We have a format specifier. Pass it to the callback.
5603d1dcd9bSDimitry Andric if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
5613d1dcd9bSDimitry Andric I - FSR.getStart())) {
5623d1dcd9bSDimitry Andric return true;
5633d1dcd9bSDimitry Andric }
5643d1dcd9bSDimitry Andric }
5653d1dcd9bSDimitry Andric assert(I == E && "Format string not exhausted");
5663d1dcd9bSDimitry Andric return false;
5673d1dcd9bSDimitry Andric }
568