/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 |