Coverage Report

Created: 2020-11-24 06:42

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