Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/extensions/tracers/xray/util.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/tracers/xray/util.h"
2
3
#include "absl/strings/ascii.h"
4
5
namespace Envoy {
6
namespace Extensions {
7
namespace Tracers {
8
namespace XRay {
9
10
// AWS X-Ray has two sources of sampling rules (wildcard patterns):
11
//
12
// 1- The manifest file (static config)
13
// 2- The X-Ray Service - periodically polled for new rules. (dynamic config)
14
//
15
// X-Ray will inspect every single request and try to match it against the set of rules it has to
16
// decide whether or not a given request should be sampled. That means this wildcard matching
17
// routine is on the hot path. I've spent a great deal of time to make this function optimal and not
18
// allocate.
19
// Using regex matching here has many downsides and it would require us to:
20
// 1- escape/lint the user input pattern to avoid messing up its meaning (think '.' character is a
21
// valid regex and URL character) 2- compile the regex and store it with every corresponding part of
22
// the rule
23
//
24
// Those two steps would add significant overhead to the tracer. Meanwhile, the following function
25
// has a comprehensive test suite and fuzz tests.
26
174
bool wildcardMatch(absl::string_view pattern, absl::string_view input) {
27
174
  if (pattern.empty()) {
28
0
    return input.empty();
29
0
  }
30
31
  // Check the special case of a single * pattern, as it's common.
32
174
  constexpr char glob = '*';
33
174
  if (pattern.size() == 1 && pattern[0] == glob) {
34
22
    return true;
35
22
  }
36
37
152
  size_t i = 0, p = 0, i_star = input.size(), p_star = 0;
38
29.1k
  while (i < input.size()) {
39
29.0k
    if (p < pattern.size() && absl::ascii_tolower(input[i]) == absl::ascii_tolower(pattern[p])) {
40
9.88k
      ++i;
41
9.88k
      ++p;
42
19.1k
    } else if (p < pattern.size() && '?' == pattern[p]) {
43
560
      ++i;
44
560
      ++p;
45
18.5k
    } else if (p < pattern.size() && pattern[p] == glob) {
46
3.15k
      i_star = i;
47
3.15k
      p_star = p++;
48
15.4k
    } else if (i_star != input.size()) {
49
15.4k
      i = ++i_star;
50
15.4k
      p = p_star + 1;
51
15.4k
    } else {
52
27
      return false;
53
27
    }
54
29.0k
  }
55
56
364
  while (p < pattern.size() && pattern[p] == glob) {
57
239
    ++p;
58
239
  }
59
60
125
  return p == pattern.size() && i == input.size();
61
152
}
62
63
} // namespace XRay
64
} // namespace Tracers
65
} // namespace Extensions
66
} // namespace Envoy