Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/AST/FormatString.h
Line
Count
Source (jump to first uncovered line)
1
//= FormatString.h - Analysis of printf/fprintf 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
// This file defines APIs for analyzing the format strings of printf, fscanf,
10
// and friends.
11
//
12
// The structure of format strings for fprintf are described in C99 7.19.6.1.
13
//
14
// The structure of format strings for fscanf are described in C99 7.19.6.2.
15
//
16
//===----------------------------------------------------------------------===//
17
18
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
19
#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
20
21
#include "clang/AST/CanonicalType.h"
22
23
namespace clang {
24
25
class TargetInfo;
26
27
//===----------------------------------------------------------------------===//
28
/// Common components of both fprintf and fscanf format strings.
29
namespace analyze_format_string {
30
31
/// Class representing optional flags with location and representation
32
/// information.
33
class OptionalFlag {
34
public:
35
  OptionalFlag(const char *Representation)
36
951k
      : representation(Representation), flag(false) {}
37
110k
  bool isSet() const { return flag; }
38
0
  void set() { flag = true; }
39
0
  void clear() { flag = false; }
40
9.78k
  void setPosition(const char *position) {
41
9.78k
    assert(position);
42
9.78k
    flag = true;
43
9.78k
    this->position = position;
44
9.78k
  }
45
111
  const char *getPosition() const {
46
111
    assert(position);
47
111
    return position;
48
111
  }
49
72
  const char *toString() const { return representation; }
50
51
  // Overloaded operators for bool like qualities
52
461k
  explicit operator bool() const { return flag; }
53
752
  OptionalFlag& operator=(const bool &rhs) {
54
752
    flag = rhs;
55
752
    return *this;  // Return a reference to myself.
56
752
  }
57
private:
58
  const char *representation;
59
  const char *position;
60
  bool flag;
61
};
62
63
/// Represents the length modifier in a format string in scanf/printf.
64
class LengthModifier {
65
public:
66
  enum Kind {
67
    None,
68
    AsChar,       // 'hh'
69
    AsShort,      // 'h'
70
    AsShortLong,  // 'hl' (OpenCL float/int vector element)
71
    AsLong,       // 'l'
72
    AsLongLong,   // 'll'
73
    AsQuad,       // 'q' (BSD, deprecated, for 64-bit integer types)
74
    AsIntMax,     // 'j'
75
    AsSizeT,      // 'z'
76
    AsPtrDiff,    // 't'
77
    AsInt32,      // 'I32' (MSVCRT, like __int32)
78
    AsInt3264,    // 'I'   (MSVCRT, like __int3264 from MIDL)
79
    AsInt64,      // 'I64' (MSVCRT, like __int64)
80
    AsLongDouble, // 'L'
81
    AsAllocate,   // for '%as', GNU extension to C90 scanf
82
    AsMAllocate,  // for '%ms', GNU extension to scanf
83
    AsWide,       // 'w' (MSVCRT, like l but only for c, C, s, S, or Z
84
    AsWideChar = AsLong // for '%ls', only makes sense for printf
85
  };
86
87
  LengthModifier()
88
96.9k
    : Position(nullptr), kind(None) {}
89
  LengthModifier(const char *pos, Kind k)
90
14.1k
    : Position(pos), kind(k) {}
91
92
471
  const char *getStart() const {
93
471
    return Position;
94
471
  }
95
96
203
  unsigned getLength() const {
97
203
    switch (kind) {
98
203
      default:
99
183
        return 1;
100
203
      case AsLongLong:
101
14
      case AsChar:
102
14
        return 2;
103
14
      case AsInt32:
104
6
      case AsInt64:
105
6
        return 3;
106
6
      case None:
107
0
        return 0;
108
203
    }
109
203
  }
110
111
255k
  Kind getKind() const { return kind; }
112
1.07k
  void setKind(Kind k) { kind = k; }
113
114
  const char *toString() const;
115
116
private:
117
  const char *Position;
118
  Kind kind;
119
};
120
121
class ConversionSpecifier {
122
public:
123
  enum Kind {
124
    InvalidSpecifier = 0,
125
    // C99 conversion specifiers.
126
    cArg,
127
    dArg,
128
    DArg, // Apple extension
129
    iArg,
130
    IntArgBeg = dArg,
131
    IntArgEnd = iArg,
132
133
    oArg,
134
    OArg, // Apple extension
135
    uArg,
136
    UArg, // Apple extension
137
    xArg,
138
    XArg,
139
    UIntArgBeg = oArg,
140
    UIntArgEnd = XArg,
141
142
    fArg,
143
    FArg,
144
    eArg,
145
    EArg,
146
    gArg,
147
    GArg,
148
    aArg,
149
    AArg,
150
    DoubleArgBeg = fArg,
151
    DoubleArgEnd = AArg,
152
153
    sArg,
154
    pArg,
155
    nArg,
156
    PercentArg,
157
    CArg,
158
    SArg,
159
160
    // Apple extension: P specifies to os_log that the data being pointed to is
161
    // to be copied by os_log. The precision indicates the number of bytes to
162
    // copy.
163
    PArg,
164
165
    // ** Printf-specific **
166
167
    ZArg, // MS extension
168
169
    // Objective-C specific specifiers.
170
    ObjCObjArg, // '@'
171
    ObjCBeg = ObjCObjArg,
172
    ObjCEnd = ObjCObjArg,
173
174
    // FreeBSD kernel specific specifiers.
175
    FreeBSDbArg,
176
    FreeBSDDArg,
177
    FreeBSDrArg,
178
    FreeBSDyArg,
179
180
    // GlibC specific specifiers.
181
    PrintErrno, // 'm'
182
183
    PrintfConvBeg = ObjCObjArg,
184
    PrintfConvEnd = PrintErrno,
185
186
    // ** Scanf-specific **
187
    ScanListArg, // '['
188
    ScanfConvBeg = ScanListArg,
189
    ScanfConvEnd = ScanListArg
190
  };
191
192
  ConversionSpecifier(bool isPrintf = true)
193
    : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr),
194
96.9k
      kind(InvalidSpecifier) {}
195
196
  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
197
57.8k
    : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}
198
199
530
  const char *getStart() const {
200
530
    return Position;
201
530
  }
202
203
0
  StringRef getCharacters() const {
204
0
    return StringRef(getStart(), getLength());
205
0
  }
206
207
229k
  bool consumesDataArgument() const {
208
229k
    switch (kind) {
209
229k
      case PrintErrno:
210
33
        assert(IsPrintf);
211
33
        return false;
212
229k
      case PercentArg:
213
659
        return false;
214
229k
      case InvalidSpecifier:
215
99
        return false;
216
229k
      default:
217
229k
        return true;
218
229k
    }
219
229k
  }
220
221
431k
  Kind getKind() const { return kind; }
222
699
  void setKind(Kind k) { kind = k; }
223
152
  unsigned getLength() const {
224
152
    return EndScanList ? 
EndScanList - Position12
:
1140
;
225
152
  }
226
79
  void setEndScanList(const char *pos) { EndScanList = pos; }
227
228
55.6k
  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
229
55.6k
    
kind == FreeBSDrArg45.9k
||
kind == FreeBSDyArg45.8k
; }
230
45.8k
  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
231
203
  bool isAnyIntArg() const { return kind >= IntArgBeg && 
kind <= UIntArgEnd188
; }
232
34.7k
  bool isDoubleArg() const {
233
34.7k
    return kind >= DoubleArgBeg && 
kind <= DoubleArgEnd33.8k
;
234
34.7k
  }
235
236
  const char *toString() const;
237
238
0
  bool isPrintfKind() const { return IsPrintf; }
239
240
  Optional<ConversionSpecifier> getStandardSpecifier() const;
241
242
protected:
243
  bool IsPrintf;
244
  const char *Position;
245
  const char *EndScanList;
246
  Kind kind;
247
};
248
249
class ArgType {
250
public:
251
  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
252
              AnyCharTy, CStrTy, WCStrTy, WIntTy };
253
254
  enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic };
255
256
private:
257
  const Kind K;
258
  QualType T;
259
  const char *Name = nullptr;
260
  bool Ptr = false;
261
262
  /// The TypeKind identifies certain well-known types like size_t and
263
  /// ptrdiff_t.
264
  enum class TypeKind { DontCare, SizeT, PtrdiffT };
265
  TypeKind TK = TypeKind::DontCare;
266
267
public:
268
28.7k
  ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}
269
458
  ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}
270
29.4k
  ArgType(CanQualType T) : K(SpecificTy), T(T) {}
271
272
36
  static ArgType Invalid() { return ArgType(InvalidTy); }
273
113k
  bool isValid() const { return K != InvalidTy; }
274
275
134
  bool isSizeT() const { return TK == TypeKind::SizeT; }
276
277
114
  bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; }
278
279
  /// Create an ArgType which corresponds to the type pointer to A.
280
1.67k
  static ArgType PtrTo(const ArgType& A) {
281
1.67k
    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
282
1.67k
    ArgType Res = A;
283
1.67k
    Res.Ptr = true;
284
1.67k
    return Res;
285
1.67k
  }
286
287
  /// Create an ArgType which corresponds to the size_t/ssize_t type.
288
62
  static ArgType makeSizeT(const ArgType &A) {
289
62
    ArgType Res = A;
290
62
    Res.TK = TypeKind::SizeT;
291
62
    return Res;
292
62
  }
293
294
  /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t
295
  /// type.
296
29
  static ArgType makePtrdiffT(const ArgType &A) {
297
29
    ArgType Res = A;
298
29
    Res.TK = TypeKind::PtrdiffT;
299
29
    return Res;
300
29
  }
301
302
  MatchKind matchesType(ASTContext &C, QualType argTy) const;
303
304
  QualType getRepresentativeType(ASTContext &C) const;
305
306
  ArgType makeVectorType(ASTContext &C, unsigned NumElts) const;
307
308
  std::string getRepresentativeTypeName(ASTContext &C) const;
309
};
310
311
class OptionalAmount {
312
public:
313
  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
314
315
  OptionalAmount(HowSpecified howSpecified,
316
                 unsigned amount,
317
                 const char *amountStart,
318
                 unsigned amountLength,
319
                 bool usesPositionalArg)
320
  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
321
24.6k
  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
322
323
  OptionalAmount(bool valid = true)
324
  : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
325
382k
  UsesPositionalArg(0), UsesDotPrefix(0) {}
326
327
  explicit OptionalAmount(unsigned Amount)
328
    : start(nullptr), length(0), hs(Constant), amt(Amount),
329
85
    UsesPositionalArg(false), UsesDotPrefix(false) {}
330
331
62.5k
  bool isInvalid() const {
332
62.5k
    return hs == Invalid;
333
62.5k
  }
334
335
172k
  HowSpecified getHowSpecified() const { return hs; }
336
66
  void setHowSpecified(HowSpecified h) { hs = h; }
337
338
111k
  bool hasDataArgument() const { return hs == Arg; }
339
340
850
  unsigned getArgIndex() const {
341
850
    assert(hasDataArgument());
342
850
    return amt;
343
850
  }
344
345
510
  unsigned getConstantAmount() const {
346
510
    assert(hs == Constant);
347
510
    return amt;
348
510
  }
349
350
90
  const char *getStart() const {
351
90
      // We include the . character if it is given.
352
90
    return start - UsesDotPrefix;
353
90
  }
354
355
25
  unsigned getConstantLength() const {
356
25
    assert(hs == Constant);
357
25
    return length + UsesDotPrefix;
358
25
  }
359
360
  ArgType getArgType(ASTContext &Ctx) const;
361
362
  void toString(raw_ostream &os) const;
363
364
4
  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
365
2
  unsigned getPositionalArgIndex() const {
366
2
    assert(hasDataArgument());
367
2
    return amt + 1;
368
2
  }
369
370
0
  bool usesDotPrefix() const { return UsesDotPrefix; }
371
2.15k
  void setUsesDotPrefix() { UsesDotPrefix = true; }
372
373
private:
374
  const char *start;
375
  unsigned length;
376
  HowSpecified hs;
377
  unsigned amt;
378
  bool UsesPositionalArg : 1;
379
  bool UsesDotPrefix;
380
};
381
382
383
class FormatSpecifier {
384
protected:
385
  LengthModifier LM;
386
  OptionalAmount FieldWidth;
387
  ConversionSpecifier CS;
388
  OptionalAmount VectorNumElts;
389
390
  /// Positional arguments, an IEEE extension:
391
  ///  IEEE Std 1003.1, 2004 Edition
392
  ///  http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
393
  bool UsesPositionalArg;
394
  unsigned argIndex;
395
public:
396
  FormatSpecifier(bool isPrintf)
397
    : CS(isPrintf), VectorNumElts(false),
398
96.9k
      UsesPositionalArg(false), argIndex(0) {}
399
400
14.1k
  void setLengthModifier(LengthModifier lm) {
401
14.1k
    LM = lm;
402
14.1k
  }
403
404
63
  void setUsesPositionalArg() { UsesPositionalArg = true; }
405
406
57.4k
  void setArgIndex(unsigned i) {
407
57.4k
    argIndex = i;
408
57.4k
  }
409
410
57.5k
  unsigned getArgIndex() const {
411
57.5k
    return argIndex;
412
57.5k
  }
413
414
7
  unsigned getPositionalArgIndex() const {
415
7
    return argIndex + 1;
416
7
  }
417
418
203
  const LengthModifier &getLengthModifier() const {
419
203
    return LM;
420
203
  }
421
422
57.3k
  const OptionalAmount &getFieldWidth() const {
423
57.3k
    return FieldWidth;
424
57.3k
  }
425
426
156
  void setVectorNumElts(const OptionalAmount &Amt) {
427
156
    VectorNumElts = Amt;
428
156
  }
429
430
0
  const OptionalAmount &getVectorNumElts() const {
431
0
    return VectorNumElts;
432
0
  }
433
434
56.2k
  void setFieldWidth(const OptionalAmount &Amt) {
435
56.2k
    FieldWidth = Amt;
436
56.2k
  }
437
438
3.25k
  bool usesPositionalArg() const { return UsesPositionalArg; }
439
440
  bool hasValidLengthModifier(const TargetInfo &Target,
441
                              const LangOptions &LO) const;
442
443
  bool hasStandardLengthModifier() const;
444
445
  Optional<LengthModifier> getCorrectedLengthModifier() const;
446
447
  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
448
449
  bool hasStandardLengthConversionCombination() const;
450
451
  /// For a TypedefType QT, if it is a named integer type such as size_t,
452
  /// assign the appropriate value to LM and return true.
453
  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
454
};
455
456
} // end analyze_format_string namespace
457
458
//===----------------------------------------------------------------------===//
459
/// Pieces specific to fprintf format strings.
460
461
namespace analyze_printf {
462
463
class PrintfConversionSpecifier :
464
  public analyze_format_string::ConversionSpecifier  {
465
public:
466
  PrintfConversionSpecifier()
467
0
    : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}
468
469
  PrintfConversionSpecifier(const char *pos, Kind k)
470
56.2k
    : ConversionSpecifier(true, pos, k) {}
471
472
54.9k
  bool isObjCArg() const { return kind >= ObjCBeg && 
kind <= ObjCEnd41
; }
473
0
  bool isDoubleArg() const { return kind >= DoubleArgBeg &&
474
0
                                    kind <= DoubleArgEnd; }
475
476
0
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
477
0
    return CS->isPrintfKind();
478
0
  }
479
};
480
481
using analyze_format_string::ArgType;
482
using analyze_format_string::LengthModifier;
483
using analyze_format_string::OptionalAmount;
484
using analyze_format_string::OptionalFlag;
485
486
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
487
  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
488
  OptionalFlag IsLeftJustified; // '-'
489
  OptionalFlag HasPlusPrefix; // '+'
490
  OptionalFlag HasSpacePrefix; // ' '
491
  OptionalFlag HasAlternativeForm; // '#'
492
  OptionalFlag HasLeadingZeroes; // '0'
493
  OptionalFlag HasObjCTechnicalTerm; // '[tt]'
494
  OptionalFlag IsPrivate;            // '{private}'
495
  OptionalFlag IsPublic;             // '{public}'
496
  OptionalFlag IsSensitive;          // '{sensitive}'
497
  OptionalAmount Precision;
498
  StringRef MaskType;
499
500
  ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
501
502
public:
503
  PrintfSpecifier()
504
      : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
505
        IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
506
        HasAlternativeForm("#"), HasLeadingZeroes("0"),
507
        HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public"),
508
94.9k
        IsSensitive("sensitive") {}
509
510
  static PrintfSpecifier Parse(const char *beg, const char *end);
511
512
    // Methods for incrementally constructing the PrintfSpecifier.
513
56.2k
  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
514
56.2k
    CS = cs;
515
56.2k
  }
516
14
  void setHasThousandsGrouping(const char *position) {
517
14
    HasThousandsGrouping.setPosition(position);
518
14
  }
519
186
  void setIsLeftJustified(const char *position) {
520
186
    IsLeftJustified.setPosition(position);
521
186
  }
522
38
  void setHasPlusPrefix(const char *position) {
523
38
    HasPlusPrefix.setPosition(position);
524
38
  }
525
31
  void setHasSpacePrefix(const char *position) {
526
31
    HasSpacePrefix.setPosition(position);
527
31
  }
528
36
  void setHasAlternativeForm(const char *position) {
529
36
    HasAlternativeForm.setPosition(position);
530
36
  }
531
9.37k
  void setHasLeadingZeros(const char *position) {
532
9.37k
    HasLeadingZeroes.setPosition(position);
533
9.37k
  }
534
13
  void setHasObjCTechnicalTerm(const char *position) {
535
13
    HasObjCTechnicalTerm.setPosition(position);
536
13
  }
537
29
  void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }
538
26
  void setIsPublic(const char *position) { IsPublic.setPosition(position); }
539
8
  void setIsSensitive(const char *position) {
540
8
    IsSensitive.setPosition(position);
541
8
  }
542
0
  void setUsesPositionalArg() { UsesPositionalArg = true; }
543
544
    // Methods for querying the format specifier.
545
546
168k
  const PrintfConversionSpecifier &getConversionSpecifier() const {
547
168k
    return cast<PrintfConversionSpecifier>(CS);
548
168k
  }
549
550
2.15k
  void setPrecision(const OptionalAmount &Amt) {
551
2.15k
    Precision = Amt;
552
2.15k
    Precision.setUsesDotPrefix();
553
2.15k
  }
554
555
55.7k
  const OptionalAmount &getPrecision() const {
556
55.7k
    return Precision;
557
55.7k
  }
558
559
55.8k
  bool consumesDataArgument() const {
560
55.8k
    return getConversionSpecifier().consumesDataArgument();
561
55.8k
  }
562
563
  /// Returns the builtin type that a data argument
564
  /// paired with this format specifier should have.  This method
565
  /// will return null if the format specifier does not have
566
  /// a matching data argument or the matching argument matches
567
  /// more than one type.
568
  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
569
570
2
  const OptionalFlag &hasThousandsGrouping() const {
571
2
      return HasThousandsGrouping;
572
2
  }
573
9.37k
  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
574
35
  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
575
5
  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
576
55.3k
  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
577
55.3k
  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
578
0
  const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
579
55.3k
  const OptionalFlag &isPrivate() const { return IsPrivate; }
580
55.3k
  const OptionalFlag &isPublic() const { return IsPublic; }
581
123
  const OptionalFlag &isSensitive() const { return IsSensitive; }
582
170k
  bool usesPositionalArg() const { return UsesPositionalArg; }
583
584
123
  StringRef getMaskType() const { return MaskType; }
585
17
  void setMaskType(StringRef S) { MaskType = S; }
586
587
  /// Changes the specifier and length according to a QualType, retaining any
588
  /// flags or options. Returns true on success, or false when a conversion
589
  /// was not successful.
590
  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,
591
               bool IsObjCLiteral);
592
593
  void toString(raw_ostream &os) const;
594
595
  // Validation methods - to check if any element results in undefined behavior
596
  bool hasValidPlusPrefix() const;
597
  bool hasValidAlternativeForm() const;
598
  bool hasValidLeadingZeros() const;
599
  bool hasValidSpacePrefix() const;
600
  bool hasValidLeftJustified() const;
601
  bool hasValidThousandsGroupingPrefix() const;
602
603
  bool hasValidPrecision() const;
604
  bool hasValidFieldWidth() const;
605
};
606
}  // end analyze_printf namespace
607
608
//===----------------------------------------------------------------------===//
609
/// Pieces specific to fscanf format strings.
610
611
namespace analyze_scanf {
612
613
class ScanfConversionSpecifier :
614
    public analyze_format_string::ConversionSpecifier  {
615
public:
616
  ScanfConversionSpecifier()
617
0
    : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}
618
619
  ScanfConversionSpecifier(const char *pos, Kind k)
620
1.61k
    : ConversionSpecifier(false, pos, k) {}
621
622
0
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
623
0
    return !CS->isPrintfKind();
624
0
  }
625
};
626
627
using analyze_format_string::ArgType;
628
using analyze_format_string::LengthModifier;
629
using analyze_format_string::OptionalAmount;
630
using analyze_format_string::OptionalFlag;
631
632
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
633
  OptionalFlag SuppressAssignment; // '*'
634
public:
635
  ScanfSpecifier() :
636
    FormatSpecifier(/* isPrintf = */ false),
637
2.02k
    SuppressAssignment("*") {}
638
639
33
  void setSuppressAssignment(const char *position) {
640
33
    SuppressAssignment.setPosition(position);
641
33
  }
642
643
1.57k
  const OptionalFlag &getSuppressAssignment() const {
644
1.57k
    return SuppressAssignment;
645
1.57k
  }
646
647
1.60k
  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
648
1.60k
    CS = cs;
649
1.60k
  }
650
651
3.20k
  const ScanfConversionSpecifier &getConversionSpecifier() const {
652
3.20k
    return cast<ScanfConversionSpecifier>(CS);
653
3.20k
  }
654
655
3.17k
  bool consumesDataArgument() const {
656
3.17k
    return CS.consumesDataArgument() && 
!SuppressAssignment3.15k
;
657
3.17k
  }
658
659
  ArgType getArgType(ASTContext &Ctx) const;
660
661
  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
662
               ASTContext &Ctx);
663
664
  void toString(raw_ostream &os) const;
665
666
  static ScanfSpecifier Parse(const char *beg, const char *end);
667
};
668
669
} // end analyze_scanf namespace
670
671
//===----------------------------------------------------------------------===//
672
// Parsing and processing of format strings (both fprintf and fscanf).
673
674
namespace analyze_format_string {
675
676
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
677
678
class FormatStringHandler {
679
public:
680
43.0k
  FormatStringHandler() {}
681
  virtual ~FormatStringHandler();
682
683
0
  virtual void HandleNullChar(const char *nullCharacter) {}
684
685
4
  virtual void HandlePosition(const char *startPos, unsigned posLen) {}
686
687
  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
688
0
                                     PositionContext p) {}
689
690
0
  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
691
692
  virtual void HandleIncompleteSpecifier(const char *startSpecifier,
693
8
                                         unsigned specifierLen) {}
694
695
  virtual void HandleEmptyObjCModifierFlag(const char *startFlags,
696
0
                                           unsigned flagsLen) {}
697
698
  virtual void HandleInvalidObjCModifierFlag(const char *startFlag,
699
0
                                             unsigned flagLen) {}
700
701
  virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
702
                                            const char *flagsEnd,
703
1
                                            const char *conversionPosition) {}
704
  // Printf-specific handlers.
705
706
  virtual bool HandleInvalidPrintfConversionSpecifier(
707
                                      const analyze_printf::PrintfSpecifier &FS,
708
                                      const char *startSpecifier,
709
13
                                      unsigned specifierLen) {
710
13
    return true;
711
13
  }
712
713
  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
714
                                     const char *startSpecifier,
715
0
                                     unsigned specifierLen) {
716
0
    return true;
717
0
  }
718
719
  /// Handle mask types whose sizes are not between one and eight bytes.
720
0
  virtual void handleInvalidMaskType(StringRef MaskType) {}
721
722
    // Scanf-specific handlers.
723
724
  virtual bool HandleInvalidScanfConversionSpecifier(
725
                                        const analyze_scanf::ScanfSpecifier &FS,
726
                                        const char *startSpecifier,
727
0
                                        unsigned specifierLen) {
728
0
    return true;
729
0
  }
730
731
  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
732
                                    const char *startSpecifier,
733
0
                                    unsigned specifierLen) {
734
0
    return true;
735
0
  }
736
737
0
  virtual void HandleIncompleteScanList(const char *start, const char *end) {}
738
};
739
740
bool ParsePrintfString(FormatStringHandler &H,
741
                       const char *beg, const char *end, const LangOptions &LO,
742
                       const TargetInfo &Target, bool isFreeBSDKPrintf);
743
744
bool ParseFormatStringHasSArg(const char *beg, const char *end,
745
                              const LangOptions &LO, const TargetInfo &Target);
746
747
bool ParseScanfString(FormatStringHandler &H,
748
                      const char *beg, const char *end, const LangOptions &LO,
749
                      const TargetInfo &Target);
750
751
} // end analyze_format_string namespace
752
} // end clang namespace
753
#endif