Coverage Report

Created: 2024-01-17 10:31

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