Coverage Report

Created: 2018-11-02 07:17

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Analysis/Analyses/FormatString.h
Line
Count
Source (jump to first uncovered line)
1
//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines APIs for analyzing the format strings of printf, fscanf,
11
// and friends.
12
//
13
// The structure of format strings for fprintf are described in C99 7.19.6.1.
14
//
15
// The structure of format strings for fscanf are described in C99 7.19.6.2.
16
//
17
//===----------------------------------------------------------------------===//
18
19
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
20
#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
21
22
#include "clang/AST/CanonicalType.h"
23
24
namespace clang {
25
26
class TargetInfo;
27
28
//===----------------------------------------------------------------------===//
29
/// Common components of both fprintf and fscanf format strings.
30
namespace analyze_format_string {
31
32
/// Class representing optional flags with location and representation
33
/// information.
34
class OptionalFlag {
35
public:
36
  OptionalFlag(const char *Representation)
37
847k
      : representation(Representation), flag(false) {}
38
109k
  bool isSet() const { return flag; }
39
0
  void set() { flag = true; }
40
0
  void clear() { flag = false; }
41
9.73k
  void setPosition(const char *position) {
42
9.73k
    assert(position);
43
9.73k
    flag = true;
44
9.73k
    this->position = position;
45
9.73k
  }
46
111
  const char *getPosition() const {
47
111
    assert(position);
48
111
    return position;
49
111
  }
50
72
  const char *toString() const { return representation; }
51
52
  // Overloaded operators for bool like qualities
53
456k
  explicit operator bool() const { return flag; }
54
645
  OptionalFlag& operator=(const bool &rhs) {
55
645
    flag = rhs;
56
645
    return *this;  // Return a reference to myself.
57
645
  }
58
private:
59
  const char *representation;
60
  const char *position;
61
  bool flag;
62
};
63
64
/// Represents the length modifier in a format string in scanf/printf.
65
0
class LengthModifier {
66
public:
67
  enum Kind {
68
    None,
69
    AsChar,       // 'hh'
70
    AsShort,      // 'h'
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
95.8k
    : Position(nullptr), kind(None) {}
89
  LengthModifier(const char *pos, Kind k)
90
13.9k
    : Position(pos), kind(k) {}
91
92
393
  const char *getStart() const {
93
393
    return Position;
94
393
  }
95
96
164
  unsigned getLength() const {
97
164
    switch (kind) {
98
164
      default:
99
144
        return 1;
100
164
      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
164
    }
109
164
  }
110
111
252k
  Kind getKind() const { return kind; }
112
974
  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
0
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
95.8k
      kind(InvalidSpecifier) {}
195
196
  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
197
57.0k
    : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {}
198
199
498
  const char *getStart() const {
200
498
    return Position;
201
498
  }
202
203
0
  StringRef getCharacters() const {
204
0
    return StringRef(getStart(), getLength());
205
0
  }
206
207
227k
  bool consumesDataArgument() const {
208
227k
    switch (kind) {
209
227k
      case PrintErrno:
210
29
        assert(IsPrintf);
211
29
        return false;
212
227k
      case PercentArg:
213
651
        return false;
214
227k
      case InvalidSpecifier:
215
79
        return false;
216
227k
      default:
217
226k
        return true;
218
227k
    }
219
227k
  }
220
221
427k
  Kind getKind() const { return kind; }
222
614
  void setKind(Kind k) { kind = k; }
223
136
  unsigned getLength() const {
224
136
    return EndScanList ? 
EndScanList - Position12
:
1124
;
225
136
  }
226
79
  void setEndScanList(const char *pos) { EndScanList = pos; }
227
228
55.0k
  bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) ||
229
55.0k
    
kind == FreeBSDrArg45.5k
||
kind == FreeBSDyArg45.5k
; }
230
45.5k
  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
231
164
  bool isAnyIntArg() const { return kind >= IntArgBeg && 
kind <= UIntArgEnd149
; }
232
0
  bool isDoubleArg() const {
233
0
    return kind >= DoubleArgBeg && kind <= DoubleArgEnd;
234
0
  }
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.5k
  ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {}
269
247
  ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {}
270
28.8k
  ArgType(CanQualType T) : K(SpecificTy), T(T) {}
271
272
16
  static ArgType Invalid() { return ArgType(InvalidTy); }
273
56.8k
  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.56k
  static ArgType PtrTo(const ArgType& A) {
281
1.56k
    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
282
1.56k
    ArgType Res = A;
283
1.56k
    Res.Ptr = true;
284
1.56k
    return Res;
285
1.56k
  }
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
  std::string getRepresentativeTypeName(ASTContext &C) const;
307
};
308
309
0
class OptionalAmount {
310
public:
311
  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
312
313
  OptionalAmount(HowSpecified howSpecified,
314
                 unsigned amount,
315
                 const char *amountStart,
316
                 unsigned amountLength,
317
                 bool usesPositionalArg)
318
  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
319
24.1k
  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
320
321
  OptionalAmount(bool valid = true)
322
  : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
323
281k
  UsesPositionalArg(0), UsesDotPrefix(0) {}
324
325
63
  bool isInvalid() const {
326
63
    return hs == Invalid;
327
63
  }
328
329
169k
  HowSpecified getHowSpecified() const { return hs; }
330
54
  void setHowSpecified(HowSpecified h) { hs = h; }
331
332
110k
  bool hasDataArgument() const { return hs == Arg; }
333
334
842
  unsigned getArgIndex() const {
335
842
    assert(hasDataArgument());
336
842
    return amt;
337
842
  }
338
339
168
  unsigned getConstantAmount() const {
340
168
    assert(hs == Constant);
341
168
    return amt;
342
168
  }
343
344
90
  const char *getStart() const {
345
90
      // We include the . character if it is given.
346
90
    return start - UsesDotPrefix;
347
90
  }
348
349
25
  unsigned getConstantLength() const {
350
25
    assert(hs == Constant);
351
25
    return length + UsesDotPrefix;
352
25
  }
353
354
  ArgType getArgType(ASTContext &Ctx) const;
355
356
  void toString(raw_ostream &os) const;
357
358
4
  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
359
2
  unsigned getPositionalArgIndex() const {
360
2
    assert(hasDataArgument());
361
2
    return amt + 1;
362
2
  }
363
364
0
  bool usesDotPrefix() const { return UsesDotPrefix; }
365
2.09k
  void setUsesDotPrefix() { UsesDotPrefix = true; }
366
367
private:
368
  const char *start;
369
  unsigned length;
370
  HowSpecified hs;
371
  unsigned amt;
372
  bool UsesPositionalArg : 1;
373
  bool UsesDotPrefix;
374
};
375
376
377
class FormatSpecifier {
378
protected:
379
  LengthModifier LM;
380
  OptionalAmount FieldWidth;
381
  ConversionSpecifier CS;
382
  /// Positional arguments, an IEEE extension:
383
  ///  IEEE Std 1003.1, 2004 Edition
384
  ///  http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
385
  bool UsesPositionalArg;
386
  unsigned argIndex;
387
public:
388
  FormatSpecifier(bool isPrintf)
389
95.8k
    : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
390
391
13.9k
  void setLengthModifier(LengthModifier lm) {
392
13.9k
    LM = lm;
393
13.9k
  }
394
395
63
  void setUsesPositionalArg() { UsesPositionalArg = true; }
396
397
56.7k
  void setArgIndex(unsigned i) {
398
56.7k
    argIndex = i;
399
56.7k
  }
400
401
56.7k
  unsigned getArgIndex() const {
402
56.7k
    return argIndex;
403
56.7k
  }
404
405
7
  unsigned getPositionalArgIndex() const {
406
7
    return argIndex + 1;
407
7
  }
408
409
164
  const LengthModifier &getLengthModifier() const {
410
164
    return LM;
411
164
  }
412
413
56.6k
  const OptionalAmount &getFieldWidth() const {
414
56.6k
    return FieldWidth;
415
56.6k
  }
416
417
55.5k
  void setFieldWidth(const OptionalAmount &Amt) {
418
55.5k
    FieldWidth = Amt;
419
55.5k
  }
420
421
3.03k
  bool usesPositionalArg() const { return UsesPositionalArg; }
422
423
  bool hasValidLengthModifier(const TargetInfo &Target) const;
424
425
  bool hasStandardLengthModifier() const;
426
427
  Optional<LengthModifier> getCorrectedLengthModifier() const;
428
429
  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
430
431
  bool hasStandardLengthConversionCombination() const;
432
433
  /// For a TypedefType QT, if it is a named integer type such as size_t,
434
  /// assign the appropriate value to LM and return true.
435
  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
436
};
437
438
} // end analyze_format_string namespace
439
440
//===----------------------------------------------------------------------===//
441
/// Pieces specific to fprintf format strings.
442
443
namespace analyze_printf {
444
445
class PrintfConversionSpecifier :
446
  public analyze_format_string::ConversionSpecifier  {
447
public:
448
  PrintfConversionSpecifier()
449
    : ConversionSpecifier(true, nullptr, InvalidSpecifier) {}
450
451
  PrintfConversionSpecifier(const char *pos, Kind k)
452
55.5k
    : ConversionSpecifier(true, pos, k) {}
453
454
54.4k
  bool isObjCArg() const { return kind >= ObjCBeg && 
kind <= ObjCEnd41
; }
455
32.7k
  bool isDoubleArg() const { return kind >= DoubleArgBeg &&
456
32.7k
                                    kind <= DoubleArgEnd; }
457
458
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
459
    return CS->isPrintfKind();
460
  }
461
};
462
463
using analyze_format_string::ArgType;
464
using analyze_format_string::LengthModifier;
465
using analyze_format_string::OptionalAmount;
466
using analyze_format_string::OptionalFlag;
467
468
class PrintfSpecifier : public analyze_format_string::FormatSpecifier {
469
  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
470
  OptionalFlag IsLeftJustified; // '-'
471
  OptionalFlag HasPlusPrefix; // '+'
472
  OptionalFlag HasSpacePrefix; // ' '
473
  OptionalFlag HasAlternativeForm; // '#'
474
  OptionalFlag HasLeadingZeroes; // '0'
475
  OptionalFlag HasObjCTechnicalTerm; // '[tt]'
476
  OptionalFlag IsPrivate;            // '{private}'
477
  OptionalFlag IsPublic;             // '{public}'
478
  OptionalAmount Precision;
479
public:
480
  PrintfSpecifier()
481
      : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"),
482
        IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "),
483
        HasAlternativeForm("#"), HasLeadingZeroes("0"),
484
93.9k
        HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {}
485
486
  static PrintfSpecifier Parse(const char *beg, const char *end);
487
488
    // Methods for incrementally constructing the PrintfSpecifier.
489
55.5k
  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
490
55.5k
    CS = cs;
491
55.5k
  }
492
14
  void setHasThousandsGrouping(const char *position) {
493
14
    HasThousandsGrouping.setPosition(position);
494
14
  }
495
184
  void setIsLeftJustified(const char *position) {
496
184
    IsLeftJustified.setPosition(position);
497
184
  }
498
38
  void setHasPlusPrefix(const char *position) {
499
38
    HasPlusPrefix.setPosition(position);
500
38
  }
501
31
  void setHasSpacePrefix(const char *position) {
502
31
    HasSpacePrefix.setPosition(position);
503
31
  }
504
36
  void setHasAlternativeForm(const char *position) {
505
36
    HasAlternativeForm.setPosition(position);
506
36
  }
507
9.35k
  void setHasLeadingZeros(const char *position) {
508
9.35k
    HasLeadingZeroes.setPosition(position);
509
9.35k
  }
510
13
  void setHasObjCTechnicalTerm(const char *position) {
511
13
    HasObjCTechnicalTerm.setPosition(position);
512
13
  }
513
13
  void setIsPrivate(const char *position) { IsPrivate.setPosition(position); }
514
10
  void setIsPublic(const char *position) { IsPublic.setPosition(position); }
515
0
  void setUsesPositionalArg() { UsesPositionalArg = true; }
516
517
    // Methods for querying the format specifier.
518
519
166k
  const PrintfConversionSpecifier &getConversionSpecifier() const {
520
166k
    return cast<PrintfConversionSpecifier>(CS);
521
166k
  }
522
523
2.09k
  void setPrecision(const OptionalAmount &Amt) {
524
2.09k
    Precision = Amt;
525
2.09k
    Precision.setUsesDotPrefix();
526
2.09k
  }
527
528
55.1k
  const OptionalAmount &getPrecision() const {
529
55.1k
    return Precision;
530
55.1k
  }
531
532
55.1k
  bool consumesDataArgument() const {
533
55.1k
    return getConversionSpecifier().consumesDataArgument();
534
55.1k
  }
535
536
  /// Returns the builtin type that a data argument
537
  /// paired with this format specifier should have.  This method
538
  /// will return null if the format specifier does not have
539
  /// a matching data argument or the matching argument matches
540
  /// more than one type.
541
  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
542
543
2
  const OptionalFlag &hasThousandsGrouping() const {
544
2
      return HasThousandsGrouping;
545
2
  }
546
9.36k
  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
547
35
  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
548
5
  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
549
54.8k
  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
550
54.8k
  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
551
0
  const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; }
552
54.7k
  const OptionalFlag &isPrivate() const { return IsPrivate; }
553
54.7k
  const OptionalFlag &isPublic() const { return IsPublic; }
554
168k
  bool usesPositionalArg() const { return UsesPositionalArg; }
555
556
  /// Changes the specifier and length according to a QualType, retaining any
557
  /// flags or options. Returns true on success, or false when a conversion
558
  /// was not successful.
559
  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,
560
               bool IsObjCLiteral);
561
562
  void toString(raw_ostream &os) const;
563
564
  // Validation methods - to check if any element results in undefined behavior
565
  bool hasValidPlusPrefix() const;
566
  bool hasValidAlternativeForm() const;
567
  bool hasValidLeadingZeros() const;
568
  bool hasValidSpacePrefix() const;
569
  bool hasValidLeftJustified() const;
570
  bool hasValidThousandsGroupingPrefix() const;
571
572
  bool hasValidPrecision() const;
573
  bool hasValidFieldWidth() const;
574
};
575
}  // end analyze_printf namespace
576
577
//===----------------------------------------------------------------------===//
578
/// Pieces specific to fscanf format strings.
579
580
namespace analyze_scanf {
581
582
class ScanfConversionSpecifier :
583
    public analyze_format_string::ConversionSpecifier  {
584
public:
585
  ScanfConversionSpecifier()
586
    : ConversionSpecifier(false, nullptr, InvalidSpecifier) {}
587
588
  ScanfConversionSpecifier(const char *pos, Kind k)
589
1.50k
    : ConversionSpecifier(false, pos, k) {}
590
591
  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
592
    return !CS->isPrintfKind();
593
  }
594
};
595
596
using analyze_format_string::ArgType;
597
using analyze_format_string::LengthModifier;
598
using analyze_format_string::OptionalAmount;
599
using analyze_format_string::OptionalFlag;
600
601
class ScanfSpecifier : public analyze_format_string::FormatSpecifier {
602
  OptionalFlag SuppressAssignment; // '*'
603
public:
604
  ScanfSpecifier() :
605
    FormatSpecifier(/* isPrintf = */ false),
606
1.91k
    SuppressAssignment("*") {}
607
608
33
  void setSuppressAssignment(const char *position) {
609
33
    SuppressAssignment.setPosition(position);
610
33
  }
611
612
1.46k
  const OptionalFlag &getSuppressAssignment() const {
613
1.46k
    return SuppressAssignment;
614
1.46k
  }
615
616
1.49k
  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
617
1.49k
    CS = cs;
618
1.49k
  }
619
620
2.98k
  const ScanfConversionSpecifier &getConversionSpecifier() const {
621
2.98k
    return cast<ScanfConversionSpecifier>(CS);
622
2.98k
  }
623
624
2.95k
  bool consumesDataArgument() const {
625
2.95k
    return CS.consumesDataArgument() && 
!SuppressAssignment2.93k
;
626
2.95k
  }
627
628
  ArgType getArgType(ASTContext &Ctx) const;
629
630
  bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt,
631
               ASTContext &Ctx);
632
633
  void toString(raw_ostream &os) const;
634
635
  static ScanfSpecifier Parse(const char *beg, const char *end);
636
};
637
638
} // end analyze_scanf namespace
639
640
//===----------------------------------------------------------------------===//
641
// Parsing and processing of format strings (both fprintf and fscanf).
642
643
namespace analyze_format_string {
644
645
enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
646
647
class FormatStringHandler {
648
public:
649
42.4k
  FormatStringHandler() {}
650
  virtual ~FormatStringHandler();
651
652
0
  virtual void HandleNullChar(const char *nullCharacter) {}
653
654
4
  virtual void HandlePosition(const char *startPos, unsigned posLen) {}
655
656
  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
657
0
                                     PositionContext p) {}
658
659
0
  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
660
661
  virtual void HandleIncompleteSpecifier(const char *startSpecifier,
662
4
                                         unsigned specifierLen) {}
663
664
  virtual void HandleEmptyObjCModifierFlag(const char *startFlags,
665
0
                                           unsigned flagsLen) {}
666
667
  virtual void HandleInvalidObjCModifierFlag(const char *startFlag,
668
0
                                             unsigned flagLen) {}
669
670
  virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart,
671
                                            const char *flagsEnd,
672
1
                                            const char *conversionPosition) {}
673
  // Printf-specific handlers.
674
675
  virtual bool HandleInvalidPrintfConversionSpecifier(
676
                                      const analyze_printf::PrintfSpecifier &FS,
677
                                      const char *startSpecifier,
678
9
                                      unsigned specifierLen) {
679
9
    return true;
680
9
  }
681
682
  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
683
                                     const char *startSpecifier,
684
0
                                     unsigned specifierLen) {
685
0
    return true;
686
0
  }
687
688
    // Scanf-specific handlers.
689
690
  virtual bool HandleInvalidScanfConversionSpecifier(
691
                                        const analyze_scanf::ScanfSpecifier &FS,
692
                                        const char *startSpecifier,
693
0
                                        unsigned specifierLen) {
694
0
    return true;
695
0
  }
696
697
  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
698
                                    const char *startSpecifier,
699
0
                                    unsigned specifierLen) {
700
0
    return true;
701
0
  }
702
703
0
  virtual void HandleIncompleteScanList(const char *start, const char *end) {}
704
};
705
706
bool ParsePrintfString(FormatStringHandler &H,
707
                       const char *beg, const char *end, const LangOptions &LO,
708
                       const TargetInfo &Target, bool isFreeBSDKPrintf);
709
710
bool ParseFormatStringHasSArg(const char *beg, const char *end,
711
                              const LangOptions &LO, const TargetInfo &Target);
712
713
bool ParseScanfString(FormatStringHandler &H,
714
                      const char *beg, const char *end, const LangOptions &LO,
715
                      const TargetInfo &Target);
716
717
} // end analyze_format_string namespace
718
} // end clang namespace
719
#endif