GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/sanitizer.cc
Date: 2026-10-04 02:40:33
Exec Total Coverage
Lines: 69 71 97.2%
Branches: 40 49 81.6%

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
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 15834 CharRange::CharRange(const char range_begin, const char range_end) {
21 15834 range_begin_ = range_begin;
22 15834 range_end_ = range_end;
23 15834 }
24
25
26 15376 CharRange::CharRange(const char single_char) {
27 15376 range_begin_ = range_end_ = single_char;
28 15376 }
29
30
31 172628 bool CharRange::InRange(const char c) const {
32
4/4
✓ Branch 0 taken 136618 times.
✓ Branch 1 taken 36010 times.
✓ Branch 2 taken 104852 times.
✓ Branch 3 taken 31766 times.
172628 return (c >= range_begin_) && (c <= range_end_);
33 }
34
35
36 //------------------------------------------------------------------------------
37
38
39 14990 InputSanitizer::InputSanitizer(const string &whitelist) : max_length_(-1) {
40
1/2
✓ Branch 1 taken 14990 times.
✗ Branch 2 not taken.
14990 InitValidRanges(whitelist);
41 14990 }
42
43
44 108 InputSanitizer::InputSanitizer(const string &whitelist, int max_length)
45 108 : max_length_(max_length) {
46
1/2
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
108 InitValidRanges(whitelist);
47 108 }
48
49
50 15098 void InputSanitizer::InitValidRanges(const std::string &whitelist) {
51 // Parse the whitelist
52 15098 const unsigned length = whitelist.length();
53 15098 unsigned pickup_pos = 0;
54
2/2
✓ Branch 0 taken 47044 times.
✓ Branch 1 taken 15098 times.
62142 for (unsigned i = 0; i < length; ++i) {
55
7/8
✓ Branch 0 taken 31994 times.
✓ Branch 1 taken 15050 times.
✓ Branch 3 taken 15834 times.
✓ Branch 4 taken 16160 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 15834 times.
✓ Branch 7 taken 31210 times.
✓ Branch 8 taken 15834 times.
47044 if ((i + 1 >= length) || (whitelist[i + 1] == ' ') || (i == length - 1)) {
56
1/2
✓ Branch 1 taken 31210 times.
✗ Branch 2 not taken.
31210 const string range = whitelist.substr(pickup_pos, i - pickup_pos + 1);
57
2/3
✓ Branch 1 taken 15376 times.
✓ Branch 2 taken 15834 times.
✗ Branch 3 not taken.
31210 switch (range.length()) {
58 15376 case 1:
59
1/2
✓ Branch 3 taken 15376 times.
✗ Branch 4 not taken.
15376 valid_ranges_.push_back(CharRange(range[0]));
60 15376 break;
61 15834 case 2:
62
1/2
✓ Branch 4 taken 15834 times.
✗ Branch 5 not taken.
15834 valid_ranges_.push_back(CharRange(range[0], range[1]));
63 15834 break;
64 ✗ default:
65 ✗ assert(false);
66 }
67 31210 ++i;
68 31210 pickup_pos = i + 1;
69 31210 }
70 }
71 15098 }
72
73
74 17152 bool InputSanitizer::Sanitize(std::string::const_iterator begin,
75 std::string::const_iterator end,
76 std::string *filtered_output) const {
77 17152 int pos = 0;
78 17152 bool is_sane = true;
79
2/2
✓ Branch 2 taken 121186 times.
✓ Branch 3 taken 16960 times.
138146 for (; begin != end; ++begin) {
80
2/2
✓ Branch 2 taken 104852 times.
✓ Branch 3 taken 16334 times.
121186 if (CheckRanges(*begin)) {
81
4/4
✓ Branch 0 taken 900 times.
✓ Branch 1 taken 103952 times.
✓ Branch 2 taken 192 times.
✓ Branch 3 taken 708 times.
104852 if ((max_length_ >= 0) && (pos >= max_length_)) {
82 192 is_sane = false;
83 192 break;
84 }
85 104660 filtered_output->push_back(*begin);
86 104660 pos++;
87 } else {
88 16334 is_sane = false;
89 }
90 }
91 17152 return is_sane;
92 }
93
94
95 121186 bool InputSanitizer::CheckRanges(const char chr) const {
96
2/2
✓ Branch 1 taken 172628 times.
✓ Branch 2 taken 16334 times.
188962 for (unsigned j = 0; j < valid_ranges_.size(); ++j) {
97
2/2
✓ Branch 2 taken 104852 times.
✓ Branch 3 taken 67776 times.
172628 if (valid_ranges_[j].InRange(chr)) {
98 104852 return true;
99 }
100 }
101 16334 return false;
102 }
103
104
105 1128 string InputSanitizer::Filter(const std::string &input) const {
106 1128 string filtered_output;
107
1/2
✓ Branch 1 taken 1128 times.
✗ Branch 2 not taken.
1128 Sanitize(input, &filtered_output);
108 1128 return filtered_output;
109 }
110
111
112 16120 bool InputSanitizer::IsValid(const std::string &input) const {
113 16120 string dummy;
114
1/2
✓ Branch 1 taken 16120 times.
✗ Branch 2 not taken.
32240 return Sanitize(input, &dummy);
115 16120 }
116
117
118 1224 bool IntegerSanitizer::Sanitize(std::string::const_iterator begin,
119 std::string::const_iterator end,
120 std::string *filtered_output) const {
121
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 1176 times.
1224 if (std::distance(begin, end) == 0) {
122 48 return false;
123 }
124
125
2/2
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 1080 times.
1176 if (*begin == '-') {
126 // minus is allowed as the first character!
127 96 filtered_output->push_back('-');
128 96 begin++;
129 }
130
131 1176 return InputSanitizer::Sanitize(begin, end, filtered_output);
132 }
133
134
135 480 bool PositiveIntegerSanitizer::Sanitize(std::string::const_iterator begin,
136 std::string::const_iterator end,
137 std::string *filtered_output) const {
138
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 432 times.
480 if (std::distance(begin, end) == 0) {
139 48 return false;
140 }
141
142 432 return InputSanitizer::Sanitize(begin, end, filtered_output);
143 }
144
145 } // namespace sanitizer
146
147 #ifdef CVMFS_NAMESPACE_GUARD
148 } // namespace CVMFS_NAMESPACE_GUARD
149 #endif
150