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