GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/sanitizer.cc Lines: 63 64 98.4 %
Date: 2019-02-03 02:48:13 Branches: 33 35 94.3 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 *
4
 * Provides input data sanitizer in the form of whitelist of character ranges.
5
 */
6
7
#include "cvmfs_config.h"
8
#include "sanitizer.h"
9
10
#include <cassert>
11
12
using namespace std;  // NOLINT
13
14
#ifdef CVMFS_NAMESPACE_GUARD
15
namespace CVMFS_NAMESPACE_GUARD {
16
#endif
17
18
namespace sanitizer {
19
20
1891
CharRange::CharRange(const char range_begin, const char range_end) {
21
1891
  range_begin_ = range_begin;
22
1891
  range_end_ = range_end;
23
1891
}
24
25
26
1597
CharRange::CharRange(const char single_char) {
27
1597
  range_begin_ = range_end_ = single_char;
28
1597
}
29
30
31
17518
bool CharRange::InRange(const char c) const {
32

17518
  return (c >= range_begin_) && (c <= range_end_);
33
}
34
35
36
//------------------------------------------------------------------------------
37
38
39
1577
InputSanitizer::InputSanitizer(const string &whitelist) : max_length_(-1) {
40
1577
  InitValidRanges(whitelist);
41
}
42
43
44
11
InputSanitizer::InputSanitizer(const string &whitelist, int max_length)
45
11
  : max_length_(max_length)
46
{
47
11
  InitValidRanges(whitelist);
48
}
49
50
51
1588
void InputSanitizer::InitValidRanges(const std::string &whitelist) {
52
  // Parse the whitelist
53
1588
  const unsigned length = whitelist.length();
54
1588
  unsigned pickup_pos = 0;
55
6967
  for (unsigned i = 0; i < length; ++i) {
56


5379
    if ((i+1 >= length) || (whitelist[i+1] == ' ') || (i == length-1)) {
57
3488
      const string range = whitelist.substr(pickup_pos, i-pickup_pos+1);
58
3488
      switch (range.length()) {
59
        case 1:
60
1597
          valid_ranges_.push_back(CharRange(range[0]));
61
1597
          break;
62
        case 2:
63
1891
          valid_ranges_.push_back(CharRange(range[0], range[1]));
64
1891
          break;
65
        default:
66
          assert(false);
67
      }
68
3488
      ++i;
69
3488
      pickup_pos = i+1;
70
    }
71
  }
72
1588
}
73
74
75
1825
bool InputSanitizer::Sanitize(
76
                          std::string::const_iterator   begin,
77
                          std::string::const_iterator   end,
78
                          std::string                  *filtered_output) const {
79
1825
  int pos = 0;
80
1825
  bool is_sane = true;
81
13344
  for (; begin != end; ++begin) {
82
11523
    if (CheckRanges(*begin)) {
83

8012
      if ((max_length_ >= 0) && (pos >= max_length_)) {
84
4
        is_sane = false;
85
4
        break;
86
      }
87
8008
      filtered_output->push_back(*begin);
88
8008
      pos++;
89
    } else {
90
3511
      is_sane = false;
91
    }
92
  }
93
1825
  return is_sane;
94
}
95
96
97
11523
bool InputSanitizer::CheckRanges(const char chr) const {
98
21029
  for (unsigned j = 0; j < valid_ranges_.size(); ++j) {
99
17518
    if (valid_ranges_[j].InRange(chr)) {
100
8012
      return true;
101
    }
102
  }
103
3511
  return false;
104
}
105
106
107
24
string InputSanitizer::Filter(const std::string &input) const {
108
24
  string filtered_output;
109
24
  Sanitize(input, &filtered_output);
110
24
  return filtered_output;
111
}
112
113
114
1803
bool InputSanitizer::IsValid(const std::string &input) const {
115
1803
  string dummy;
116
1803
  return Sanitize(input, &dummy);
117
}
118
119
120
70
bool IntegerSanitizer::Sanitize(
121
                          std::string::const_iterator   begin,
122
                          std::string::const_iterator   end,
123
                          std::string                  *filtered_output) const {
124
70
  if (std::distance(begin, end) == 0) {
125
1
    return false;
126
  }
127
128
69
  if (*begin == '-') {
129
    // minus is allowed as the first character!
130
2
    filtered_output->push_back('-');
131
2
    begin++;
132
  }
133
134
69
  return InputSanitizer::Sanitize(begin, end, filtered_output);
135
}
136
137
138
10
bool PositiveIntegerSanitizer::Sanitize(
139
                          std::string::const_iterator   begin,
140
                          std::string::const_iterator   end,
141
                          std::string                  *filtered_output) const {
142
10
  if (std::distance(begin, end) == 0) {
143
1
    return false;
144
  }
145
146
9
  return InputSanitizer::Sanitize(begin, end, filtered_output);
147
}
148
149
}  // namespace sanitizer
150
151
#ifdef CVMFS_NAMESPACE_GUARD
152
}  // namespace CVMFS_NAMESPACE_GUARD
153
#endif