Home | History | Annotate | Line # | Download | only in AST
      1  1.1  joerg //= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===//
      2  1.1  joerg //
      3  1.1  joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.1  joerg // See https://llvm.org/LICENSE.txt for license information.
      5  1.1  joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6  1.1  joerg //
      7  1.1  joerg //===----------------------------------------------------------------------===//
      8  1.1  joerg //
      9  1.1  joerg // Handling of format string in scanf and friends.  The structure of format
     10  1.1  joerg // strings for fscanf() are described in C99 7.19.6.2.
     11  1.1  joerg //
     12  1.1  joerg //===----------------------------------------------------------------------===//
     13  1.1  joerg 
     14  1.1  joerg #include "clang/AST/FormatString.h"
     15  1.1  joerg #include "FormatStringParsing.h"
     16  1.1  joerg #include "clang/Basic/TargetInfo.h"
     17  1.1  joerg 
     18  1.1  joerg using clang::analyze_format_string::ArgType;
     19  1.1  joerg using clang::analyze_format_string::FormatStringHandler;
     20  1.1  joerg using clang::analyze_format_string::LengthModifier;
     21  1.1  joerg using clang::analyze_format_string::OptionalAmount;
     22  1.1  joerg using clang::analyze_format_string::ConversionSpecifier;
     23  1.1  joerg using clang::analyze_scanf::ScanfConversionSpecifier;
     24  1.1  joerg using clang::analyze_scanf::ScanfSpecifier;
     25  1.1  joerg using clang::UpdateOnReturn;
     26  1.1  joerg using namespace clang;
     27  1.1  joerg 
     28  1.1  joerg typedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier>
     29  1.1  joerg         ScanfSpecifierResult;
     30  1.1  joerg 
     31  1.1  joerg static bool ParseScanList(FormatStringHandler &H,
     32  1.1  joerg                           ScanfConversionSpecifier &CS,
     33  1.1  joerg                           const char *&Beg, const char *E) {
     34  1.1  joerg   const char *I = Beg;
     35  1.1  joerg   const char *start = I - 1;
     36  1.1  joerg   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
     37  1.1  joerg 
     38  1.1  joerg   // No more characters?
     39  1.1  joerg   if (I == E) {
     40  1.1  joerg     H.HandleIncompleteScanList(start, I);
     41  1.1  joerg     return true;
     42  1.1  joerg   }
     43  1.1  joerg 
     44  1.1  joerg   // Special case: ']' is the first character.
     45  1.1  joerg   if (*I == ']') {
     46  1.1  joerg     if (++I == E) {
     47  1.1  joerg       H.HandleIncompleteScanList(start, I - 1);
     48  1.1  joerg       return true;
     49  1.1  joerg     }
     50  1.1  joerg   }
     51  1.1  joerg 
     52  1.1  joerg   // Special case: "^]" are the first characters.
     53  1.1  joerg   if (I + 1 != E && I[0] == '^' && I[1] == ']') {
     54  1.1  joerg     I += 2;
     55  1.1  joerg     if (I == E) {
     56  1.1  joerg       H.HandleIncompleteScanList(start, I - 1);
     57  1.1  joerg       return true;
     58  1.1  joerg     }
     59  1.1  joerg   }
     60  1.1  joerg 
     61  1.1  joerg   // Look for a ']' character which denotes the end of the scan list.
     62  1.1  joerg   while (*I != ']') {
     63  1.1  joerg     if (++I == E) {
     64  1.1  joerg       H.HandleIncompleteScanList(start, I - 1);
     65  1.1  joerg       return true;
     66  1.1  joerg     }
     67  1.1  joerg   }
     68  1.1  joerg 
     69  1.1  joerg   CS.setEndScanList(I);
     70  1.1  joerg   return false;
     71  1.1  joerg }
     72  1.1  joerg 
     73  1.1  joerg // FIXME: Much of this is copy-paste from ParsePrintfSpecifier.
     74  1.1  joerg // We can possibly refactor.
     75  1.1  joerg static ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H,
     76  1.1  joerg                                                 const char *&Beg,
     77  1.1  joerg                                                 const char *E,
     78  1.1  joerg                                                 unsigned &argIndex,
     79  1.1  joerg                                                 const LangOptions &LO,
     80  1.1  joerg                                                 const TargetInfo &Target) {
     81  1.1  joerg   using namespace clang::analyze_format_string;
     82  1.1  joerg   using namespace clang::analyze_scanf;
     83  1.1  joerg   const char *I = Beg;
     84  1.1  joerg   const char *Start = nullptr;
     85  1.1  joerg   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
     86  1.1  joerg 
     87  1.1  joerg     // Look for a '%' character that indicates the start of a format specifier.
     88  1.1  joerg   for ( ; I != E ; ++I) {
     89  1.1  joerg     char c = *I;
     90  1.1  joerg     if (c == '\0') {
     91  1.1  joerg         // Detect spurious null characters, which are likely errors.
     92  1.1  joerg       H.HandleNullChar(I);
     93  1.1  joerg       return true;
     94  1.1  joerg     }
     95  1.1  joerg     if (c == '%') {
     96  1.1  joerg       Start = I++;  // Record the start of the format specifier.
     97  1.1  joerg       break;
     98  1.1  joerg     }
     99  1.1  joerg   }
    100  1.1  joerg 
    101  1.1  joerg     // No format specifier found?
    102  1.1  joerg   if (!Start)
    103  1.1  joerg     return false;
    104  1.1  joerg 
    105  1.1  joerg   if (I == E) {
    106  1.1  joerg       // No more characters left?
    107  1.1  joerg     H.HandleIncompleteSpecifier(Start, E - Start);
    108  1.1  joerg     return true;
    109  1.1  joerg   }
    110  1.1  joerg 
    111  1.1  joerg   ScanfSpecifier FS;
    112  1.1  joerg   if (ParseArgPosition(H, FS, Start, I, E))
    113  1.1  joerg     return true;
    114  1.1  joerg 
    115  1.1  joerg   if (I == E) {
    116  1.1  joerg       // No more characters left?
    117  1.1  joerg     H.HandleIncompleteSpecifier(Start, E - Start);
    118  1.1  joerg     return true;
    119  1.1  joerg   }
    120  1.1  joerg 
    121  1.1  joerg   // Look for '*' flag if it is present.
    122  1.1  joerg   if (*I == '*') {
    123  1.1  joerg     FS.setSuppressAssignment(I);
    124  1.1  joerg     if (++I == E) {
    125  1.1  joerg       H.HandleIncompleteSpecifier(Start, E - Start);
    126  1.1  joerg       return true;
    127  1.1  joerg     }
    128  1.1  joerg   }
    129  1.1  joerg 
    130  1.1  joerg   // Look for the field width (if any).  Unlike printf, this is either
    131  1.1  joerg   // a fixed integer or isn't present.
    132  1.1  joerg   const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E);
    133  1.1  joerg   if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) {
    134  1.1  joerg     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
    135  1.1  joerg     FS.setFieldWidth(Amt);
    136  1.1  joerg 
    137  1.1  joerg     if (I == E) {
    138  1.1  joerg       // No more characters left?
    139  1.1  joerg       H.HandleIncompleteSpecifier(Start, E - Start);
    140  1.1  joerg       return true;
    141  1.1  joerg     }
    142  1.1  joerg   }
    143  1.1  joerg 
    144  1.1  joerg   // Look for the length modifier.
    145  1.1  joerg   if (ParseLengthModifier(FS, I, E, LO, /*IsScanf=*/true) && I == E) {
    146  1.1  joerg       // No more characters left?
    147  1.1  joerg     H.HandleIncompleteSpecifier(Start, E - Start);
    148  1.1  joerg     return true;
    149  1.1  joerg   }
    150  1.1  joerg 
    151  1.1  joerg   // Detect spurious null characters, which are likely errors.
    152  1.1  joerg   if (*I == '\0') {
    153  1.1  joerg     H.HandleNullChar(I);
    154  1.1  joerg     return true;
    155  1.1  joerg   }
    156  1.1  joerg 
    157  1.1  joerg   // Finally, look for the conversion specifier.
    158  1.1  joerg   const char *conversionPosition = I++;
    159  1.1  joerg   ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier;
    160  1.1  joerg   switch (*conversionPosition) {
    161  1.1  joerg     default:
    162  1.1  joerg       break;
    163  1.1  joerg     case '%': k = ConversionSpecifier::PercentArg;   break;
    164  1.1  joerg     case 'A': k = ConversionSpecifier::AArg; break;
    165  1.1  joerg     case 'E': k = ConversionSpecifier::EArg; break;
    166  1.1  joerg     case 'F': k = ConversionSpecifier::FArg; break;
    167  1.1  joerg     case 'G': k = ConversionSpecifier::GArg; break;
    168  1.1  joerg     case 'X': k = ConversionSpecifier::XArg; break;
    169  1.1  joerg     case 'a': k = ConversionSpecifier::aArg; break;
    170  1.1  joerg     case 'd': k = ConversionSpecifier::dArg; break;
    171  1.1  joerg     case 'e': k = ConversionSpecifier::eArg; break;
    172  1.1  joerg     case 'f': k = ConversionSpecifier::fArg; break;
    173  1.1  joerg     case 'g': k = ConversionSpecifier::gArg; break;
    174  1.1  joerg     case 'i': k = ConversionSpecifier::iArg; break;
    175  1.1  joerg     case 'n': k = ConversionSpecifier::nArg; break;
    176  1.1  joerg     case 'c': k = ConversionSpecifier::cArg; break;
    177  1.1  joerg     case 'C': k = ConversionSpecifier::CArg; break;
    178  1.1  joerg     case 'S': k = ConversionSpecifier::SArg; break;
    179  1.1  joerg     case '[': k = ConversionSpecifier::ScanListArg; break;
    180  1.1  joerg     case 'u': k = ConversionSpecifier::uArg; break;
    181  1.1  joerg     case 'x': k = ConversionSpecifier::xArg; break;
    182  1.1  joerg     case 'o': k = ConversionSpecifier::oArg; break;
    183  1.1  joerg     case 's': k = ConversionSpecifier::sArg; break;
    184  1.1  joerg     case 'p': k = ConversionSpecifier::pArg; break;
    185  1.1  joerg     // Apple extensions
    186  1.1  joerg       // Apple-specific
    187  1.1  joerg     case 'D':
    188  1.1  joerg       if (Target.getTriple().isOSDarwin())
    189  1.1  joerg         k = ConversionSpecifier::DArg;
    190  1.1  joerg       break;
    191  1.1  joerg     case 'O':
    192  1.1  joerg       if (Target.getTriple().isOSDarwin())
    193  1.1  joerg         k = ConversionSpecifier::OArg;
    194  1.1  joerg       break;
    195  1.1  joerg     case 'U':
    196  1.1  joerg       if (Target.getTriple().isOSDarwin())
    197  1.1  joerg         k = ConversionSpecifier::UArg;
    198  1.1  joerg       break;
    199  1.1  joerg   }
    200  1.1  joerg   ScanfConversionSpecifier CS(conversionPosition, k);
    201  1.1  joerg   if (k == ScanfConversionSpecifier::ScanListArg) {
    202  1.1  joerg     if (ParseScanList(H, CS, I, E))
    203  1.1  joerg       return true;
    204  1.1  joerg   }
    205  1.1  joerg   FS.setConversionSpecifier(CS);
    206  1.1  joerg   if (CS.consumesDataArgument() && !FS.getSuppressAssignment()
    207  1.1  joerg       && !FS.usesPositionalArg())
    208  1.1  joerg     FS.setArgIndex(argIndex++);
    209  1.1  joerg 
    210  1.1  joerg   // FIXME: '%' and '*' doesn't make sense.  Issue a warning.
    211  1.1  joerg   // FIXME: 'ConsumedSoFar' and '*' doesn't make sense.
    212  1.1  joerg 
    213  1.1  joerg   if (k == ScanfConversionSpecifier::InvalidSpecifier) {
    214  1.1  joerg     unsigned Len = I - Beg;
    215  1.1  joerg     if (ParseUTF8InvalidSpecifier(Beg, E, Len)) {
    216  1.1  joerg       CS.setEndScanList(Beg + Len);
    217  1.1  joerg       FS.setConversionSpecifier(CS);
    218  1.1  joerg     }
    219  1.1  joerg     // Assume the conversion takes one argument.
    220  1.1  joerg     return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, Len);
    221  1.1  joerg   }
    222  1.1  joerg   return ScanfSpecifierResult(Start, FS);
    223  1.1  joerg }
    224  1.1  joerg 
    225  1.1  joerg ArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const {
    226  1.1  joerg   const ScanfConversionSpecifier &CS = getConversionSpecifier();
    227  1.1  joerg 
    228  1.1  joerg   if (!CS.consumesDataArgument())
    229  1.1  joerg     return ArgType::Invalid();
    230  1.1  joerg 
    231  1.1  joerg   switch(CS.getKind()) {
    232  1.1  joerg     // Signed int.
    233  1.1  joerg     case ConversionSpecifier::dArg:
    234  1.1  joerg     case ConversionSpecifier::DArg:
    235  1.1  joerg     case ConversionSpecifier::iArg:
    236  1.1  joerg       switch (LM.getKind()) {
    237  1.1  joerg         case LengthModifier::None:
    238  1.1  joerg           return ArgType::PtrTo(Ctx.IntTy);
    239  1.1  joerg         case LengthModifier::AsChar:
    240  1.1  joerg           return ArgType::PtrTo(ArgType::AnyCharTy);
    241  1.1  joerg         case LengthModifier::AsShort:
    242  1.1  joerg           return ArgType::PtrTo(Ctx.ShortTy);
    243  1.1  joerg         case LengthModifier::AsLong:
    244  1.1  joerg           return ArgType::PtrTo(Ctx.LongTy);
    245  1.1  joerg         case LengthModifier::AsLongLong:
    246  1.1  joerg         case LengthModifier::AsQuad:
    247  1.1  joerg           return ArgType::PtrTo(Ctx.LongLongTy);
    248  1.1  joerg         case LengthModifier::AsInt64:
    249  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
    250  1.1  joerg         case LengthModifier::AsIntMax:
    251  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
    252  1.1  joerg         case LengthModifier::AsSizeT:
    253  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
    254  1.1  joerg         case LengthModifier::AsPtrDiff:
    255  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
    256  1.1  joerg         case LengthModifier::AsLongDouble:
    257  1.1  joerg           // GNU extension.
    258  1.1  joerg           return ArgType::PtrTo(Ctx.LongLongTy);
    259  1.1  joerg         case LengthModifier::AsAllocate:
    260  1.1  joerg         case LengthModifier::AsMAllocate:
    261  1.1  joerg         case LengthModifier::AsInt32:
    262  1.1  joerg         case LengthModifier::AsInt3264:
    263  1.1  joerg         case LengthModifier::AsWide:
    264  1.1  joerg         case LengthModifier::AsShortLong:
    265  1.1  joerg           return ArgType::Invalid();
    266  1.1  joerg       }
    267  1.1  joerg       llvm_unreachable("Unsupported LengthModifier Type");
    268  1.1  joerg 
    269  1.1  joerg     // Unsigned int.
    270  1.1  joerg     case ConversionSpecifier::oArg:
    271  1.1  joerg     case ConversionSpecifier::OArg:
    272  1.1  joerg     case ConversionSpecifier::uArg:
    273  1.1  joerg     case ConversionSpecifier::UArg:
    274  1.1  joerg     case ConversionSpecifier::xArg:
    275  1.1  joerg     case ConversionSpecifier::XArg:
    276  1.1  joerg       switch (LM.getKind()) {
    277  1.1  joerg         case LengthModifier::None:
    278  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedIntTy);
    279  1.1  joerg         case LengthModifier::AsChar:
    280  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedCharTy);
    281  1.1  joerg         case LengthModifier::AsShort:
    282  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedShortTy);
    283  1.1  joerg         case LengthModifier::AsLong:
    284  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedLongTy);
    285  1.1  joerg         case LengthModifier::AsLongLong:
    286  1.1  joerg         case LengthModifier::AsQuad:
    287  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
    288  1.1  joerg         case LengthModifier::AsInt64:
    289  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"));
    290  1.1  joerg         case LengthModifier::AsIntMax:
    291  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t"));
    292  1.1  joerg         case LengthModifier::AsSizeT:
    293  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t"));
    294  1.1  joerg         case LengthModifier::AsPtrDiff:
    295  1.1  joerg           return ArgType::PtrTo(
    296  1.1  joerg               ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
    297  1.1  joerg         case LengthModifier::AsLongDouble:
    298  1.1  joerg           // GNU extension.
    299  1.1  joerg           return ArgType::PtrTo(Ctx.UnsignedLongLongTy);
    300  1.1  joerg         case LengthModifier::AsAllocate:
    301  1.1  joerg         case LengthModifier::AsMAllocate:
    302  1.1  joerg         case LengthModifier::AsInt32:
    303  1.1  joerg         case LengthModifier::AsInt3264:
    304  1.1  joerg         case LengthModifier::AsWide:
    305  1.1  joerg         case LengthModifier::AsShortLong:
    306  1.1  joerg           return ArgType::Invalid();
    307  1.1  joerg       }
    308  1.1  joerg       llvm_unreachable("Unsupported LengthModifier Type");
    309  1.1  joerg 
    310  1.1  joerg     // Float.
    311  1.1  joerg     case ConversionSpecifier::aArg:
    312  1.1  joerg     case ConversionSpecifier::AArg:
    313  1.1  joerg     case ConversionSpecifier::eArg:
    314  1.1  joerg     case ConversionSpecifier::EArg:
    315  1.1  joerg     case ConversionSpecifier::fArg:
    316  1.1  joerg     case ConversionSpecifier::FArg:
    317  1.1  joerg     case ConversionSpecifier::gArg:
    318  1.1  joerg     case ConversionSpecifier::GArg:
    319  1.1  joerg       switch (LM.getKind()) {
    320  1.1  joerg         case LengthModifier::None:
    321  1.1  joerg           return ArgType::PtrTo(Ctx.FloatTy);
    322  1.1  joerg         case LengthModifier::AsLong:
    323  1.1  joerg           return ArgType::PtrTo(Ctx.DoubleTy);
    324  1.1  joerg         case LengthModifier::AsLongDouble:
    325  1.1  joerg           return ArgType::PtrTo(Ctx.LongDoubleTy);
    326  1.1  joerg         default:
    327  1.1  joerg           return ArgType::Invalid();
    328  1.1  joerg       }
    329  1.1  joerg 
    330  1.1  joerg     // Char, string and scanlist.
    331  1.1  joerg     case ConversionSpecifier::cArg:
    332  1.1  joerg     case ConversionSpecifier::sArg:
    333  1.1  joerg     case ConversionSpecifier::ScanListArg:
    334  1.1  joerg       switch (LM.getKind()) {
    335  1.1  joerg         case LengthModifier::None:
    336  1.1  joerg           return ArgType::PtrTo(ArgType::AnyCharTy);
    337  1.1  joerg         case LengthModifier::AsLong:
    338  1.1  joerg         case LengthModifier::AsWide:
    339  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
    340  1.1  joerg         case LengthModifier::AsAllocate:
    341  1.1  joerg         case LengthModifier::AsMAllocate:
    342  1.1  joerg           return ArgType::PtrTo(ArgType::CStrTy);
    343  1.1  joerg         case LengthModifier::AsShort:
    344  1.1  joerg           if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
    345  1.1  joerg             return ArgType::PtrTo(ArgType::AnyCharTy);
    346  1.1  joerg           LLVM_FALLTHROUGH;
    347  1.1  joerg         default:
    348  1.1  joerg           return ArgType::Invalid();
    349  1.1  joerg       }
    350  1.1  joerg     case ConversionSpecifier::CArg:
    351  1.1  joerg     case ConversionSpecifier::SArg:
    352  1.1  joerg       // FIXME: Mac OS X specific?
    353  1.1  joerg       switch (LM.getKind()) {
    354  1.1  joerg         case LengthModifier::None:
    355  1.1  joerg         case LengthModifier::AsWide:
    356  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t"));
    357  1.1  joerg         case LengthModifier::AsAllocate:
    358  1.1  joerg         case LengthModifier::AsMAllocate:
    359  1.1  joerg           return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *"));
    360  1.1  joerg         case LengthModifier::AsShort:
    361  1.1  joerg           if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
    362  1.1  joerg             return ArgType::PtrTo(ArgType::AnyCharTy);
    363  1.1  joerg           LLVM_FALLTHROUGH;
    364  1.1  joerg         default:
    365  1.1  joerg           return ArgType::Invalid();
    366  1.1  joerg       }
    367  1.1  joerg 
    368  1.1  joerg     // Pointer.
    369  1.1  joerg     case ConversionSpecifier::pArg:
    370  1.1  joerg       return ArgType::PtrTo(ArgType::CPointerTy);
    371  1.1  joerg 
    372  1.1  joerg     // Write-back.
    373  1.1  joerg     case ConversionSpecifier::nArg:
    374  1.1  joerg       switch (LM.getKind()) {
    375  1.1  joerg         case LengthModifier::None:
    376  1.1  joerg           return ArgType::PtrTo(Ctx.IntTy);
    377  1.1  joerg         case LengthModifier::AsChar:
    378  1.1  joerg           return ArgType::PtrTo(Ctx.SignedCharTy);
    379  1.1  joerg         case LengthModifier::AsShort:
    380  1.1  joerg           return ArgType::PtrTo(Ctx.ShortTy);
    381  1.1  joerg         case LengthModifier::AsLong:
    382  1.1  joerg           return ArgType::PtrTo(Ctx.LongTy);
    383  1.1  joerg         case LengthModifier::AsLongLong:
    384  1.1  joerg         case LengthModifier::AsQuad:
    385  1.1  joerg           return ArgType::PtrTo(Ctx.LongLongTy);
    386  1.1  joerg         case LengthModifier::AsInt64:
    387  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64"));
    388  1.1  joerg         case LengthModifier::AsIntMax:
    389  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
    390  1.1  joerg         case LengthModifier::AsSizeT:
    391  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
    392  1.1  joerg         case LengthModifier::AsPtrDiff:
    393  1.1  joerg           return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
    394  1.1  joerg         case LengthModifier::AsLongDouble:
    395  1.1  joerg           return ArgType(); // FIXME: Is this a known extension?
    396  1.1  joerg         case LengthModifier::AsAllocate:
    397  1.1  joerg         case LengthModifier::AsMAllocate:
    398  1.1  joerg         case LengthModifier::AsInt32:
    399  1.1  joerg         case LengthModifier::AsInt3264:
    400  1.1  joerg         case LengthModifier::AsWide:
    401  1.1  joerg         case LengthModifier::AsShortLong:
    402  1.1  joerg           return ArgType::Invalid();
    403  1.1  joerg         }
    404  1.1  joerg 
    405  1.1  joerg     default:
    406  1.1  joerg       break;
    407  1.1  joerg   }
    408  1.1  joerg 
    409  1.1  joerg   return ArgType();
    410  1.1  joerg }
    411  1.1  joerg 
    412  1.1  joerg bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
    413  1.1  joerg                              const LangOptions &LangOpt,
    414  1.1  joerg                              ASTContext &Ctx) {
    415  1.1  joerg 
    416  1.1  joerg   // %n is different from other conversion specifiers; don't try to fix it.
    417  1.1  joerg   if (CS.getKind() == ConversionSpecifier::nArg)
    418  1.1  joerg     return false;
    419  1.1  joerg 
    420  1.1  joerg   if (!QT->isPointerType())
    421  1.1  joerg     return false;
    422  1.1  joerg 
    423  1.1  joerg   QualType PT = QT->getPointeeType();
    424  1.1  joerg 
    425  1.1  joerg   // If it's an enum, get its underlying type.
    426  1.1  joerg   if (const EnumType *ETy = PT->getAs<EnumType>()) {
    427  1.1  joerg     // Don't try to fix incomplete enums.
    428  1.1  joerg     if (!ETy->getDecl()->isComplete())
    429  1.1  joerg       return false;
    430  1.1  joerg     PT = ETy->getDecl()->getIntegerType();
    431  1.1  joerg   }
    432  1.1  joerg 
    433  1.1  joerg   const BuiltinType *BT = PT->getAs<BuiltinType>();
    434  1.1  joerg   if (!BT)
    435  1.1  joerg     return false;
    436  1.1  joerg 
    437  1.1  joerg   // Pointer to a character.
    438  1.1  joerg   if (PT->isAnyCharacterType()) {
    439  1.1  joerg     CS.setKind(ConversionSpecifier::sArg);
    440  1.1  joerg     if (PT->isWideCharType())
    441  1.1  joerg       LM.setKind(LengthModifier::AsWideChar);
    442  1.1  joerg     else
    443  1.1  joerg       LM.setKind(LengthModifier::None);
    444  1.1  joerg 
    445  1.1  joerg     // If we know the target array length, we can use it as a field width.
    446  1.1  joerg     if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
    447  1.1  joerg       if (CAT->getSizeModifier() == ArrayType::Normal)
    448  1.1  joerg         FieldWidth = OptionalAmount(OptionalAmount::Constant,
    449  1.1  joerg                                     CAT->getSize().getZExtValue() - 1,
    450  1.1  joerg                                     "", 0, false);
    451  1.1  joerg 
    452  1.1  joerg     }
    453  1.1  joerg     return true;
    454  1.1  joerg   }
    455  1.1  joerg 
    456  1.1  joerg   // Figure out the length modifier.
    457  1.1  joerg   switch (BT->getKind()) {
    458  1.1  joerg     // no modifier
    459  1.1  joerg     case BuiltinType::UInt:
    460  1.1  joerg     case BuiltinType::Int:
    461  1.1  joerg     case BuiltinType::Float:
    462  1.1  joerg       LM.setKind(LengthModifier::None);
    463  1.1  joerg       break;
    464  1.1  joerg 
    465  1.1  joerg     // hh
    466  1.1  joerg     case BuiltinType::Char_U:
    467  1.1  joerg     case BuiltinType::UChar:
    468  1.1  joerg     case BuiltinType::Char_S:
    469  1.1  joerg     case BuiltinType::SChar:
    470  1.1  joerg       LM.setKind(LengthModifier::AsChar);
    471  1.1  joerg       break;
    472  1.1  joerg 
    473  1.1  joerg     // h
    474  1.1  joerg     case BuiltinType::Short:
    475  1.1  joerg     case BuiltinType::UShort:
    476  1.1  joerg       LM.setKind(LengthModifier::AsShort);
    477  1.1  joerg       break;
    478  1.1  joerg 
    479  1.1  joerg     // l
    480  1.1  joerg     case BuiltinType::Long:
    481  1.1  joerg     case BuiltinType::ULong:
    482  1.1  joerg     case BuiltinType::Double:
    483  1.1  joerg       LM.setKind(LengthModifier::AsLong);
    484  1.1  joerg       break;
    485  1.1  joerg 
    486  1.1  joerg     // ll
    487  1.1  joerg     case BuiltinType::LongLong:
    488  1.1  joerg     case BuiltinType::ULongLong:
    489  1.1  joerg       LM.setKind(LengthModifier::AsLongLong);
    490  1.1  joerg       break;
    491  1.1  joerg 
    492  1.1  joerg     // L
    493  1.1  joerg     case BuiltinType::LongDouble:
    494  1.1  joerg       LM.setKind(LengthModifier::AsLongDouble);
    495  1.1  joerg       break;
    496  1.1  joerg 
    497  1.1  joerg     // Don't know.
    498  1.1  joerg     default:
    499  1.1  joerg       return false;
    500  1.1  joerg   }
    501  1.1  joerg 
    502  1.1  joerg   // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
    503  1.1  joerg   if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
    504  1.1  joerg     namedTypeToLengthModifier(PT, LM);
    505  1.1  joerg 
    506  1.1  joerg   // If fixing the length modifier was enough, we are done.
    507  1.1  joerg   if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
    508  1.1  joerg     const analyze_scanf::ArgType &AT = getArgType(Ctx);
    509  1.1  joerg     if (AT.isValid() && AT.matchesType(Ctx, QT))
    510  1.1  joerg       return true;
    511  1.1  joerg   }
    512  1.1  joerg 
    513  1.1  joerg   // Figure out the conversion specifier.
    514  1.1  joerg   if (PT->isRealFloatingType())
    515  1.1  joerg     CS.setKind(ConversionSpecifier::fArg);
    516  1.1  joerg   else if (PT->isSignedIntegerType())
    517  1.1  joerg     CS.setKind(ConversionSpecifier::dArg);
    518  1.1  joerg   else if (PT->isUnsignedIntegerType())
    519  1.1  joerg     CS.setKind(ConversionSpecifier::uArg);
    520  1.1  joerg   else
    521  1.1  joerg     llvm_unreachable("Unexpected type");
    522  1.1  joerg 
    523  1.1  joerg   return true;
    524  1.1  joerg }
    525  1.1  joerg 
    526  1.1  joerg void ScanfSpecifier::toString(raw_ostream &os) const {
    527  1.1  joerg   os << "%";
    528  1.1  joerg 
    529  1.1  joerg   if (usesPositionalArg())
    530  1.1  joerg     os << getPositionalArgIndex() << "$";
    531  1.1  joerg   if (SuppressAssignment)
    532  1.1  joerg     os << "*";
    533  1.1  joerg 
    534  1.1  joerg   FieldWidth.toString(os);
    535  1.1  joerg   os << LM.toString();
    536  1.1  joerg   os << CS.toString();
    537  1.1  joerg }
    538  1.1  joerg 
    539  1.1  joerg bool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H,
    540  1.1  joerg                                                     const char *I,
    541  1.1  joerg                                                     const char *E,
    542  1.1  joerg                                                     const LangOptions &LO,
    543  1.1  joerg                                                     const TargetInfo &Target) {
    544  1.1  joerg 
    545  1.1  joerg   unsigned argIndex = 0;
    546  1.1  joerg 
    547  1.1  joerg   // Keep looking for a format specifier until we have exhausted the string.
    548  1.1  joerg   while (I != E) {
    549  1.1  joerg     const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex,
    550  1.1  joerg                                                           LO, Target);
    551  1.1  joerg     // Did a fail-stop error of any kind occur when parsing the specifier?
    552  1.1  joerg     // If so, don't do any more processing.
    553  1.1  joerg     if (FSR.shouldStop())
    554  1.1  joerg       return true;
    555  1.1  joerg       // Did we exhaust the string or encounter an error that
    556  1.1  joerg       // we can recover from?
    557  1.1  joerg     if (!FSR.hasValue())
    558  1.1  joerg       continue;
    559  1.1  joerg       // We have a format specifier.  Pass it to the callback.
    560  1.1  joerg     if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(),
    561  1.1  joerg                                 I - FSR.getStart())) {
    562  1.1  joerg       return true;
    563  1.1  joerg     }
    564  1.1  joerg   }
    565  1.1  joerg   assert(I == E && "Format string not exhausted");
    566  1.1  joerg   return false;
    567  1.1  joerg }
    568