percent_encoding.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
20 
22 
23 #include <stdlib.h>
24 
25 #include <cstdint>
26 #include <type_traits>
27 #include <utility>
28 
29 #include <grpc/support/log.h>
30 
32 
33 #if __cplusplus > 201103l
34 #define GRPC_PCTENCODE_CONSTEXPR_FN constexpr
35 #define GRPC_PCTENCODE_CONSTEXPR_VALUE constexpr
36 #else
37 #define GRPC_PCTENCODE_CONSTEXPR_FN
38 #define GRPC_PCTENCODE_CONSTEXPR_VALUE const
39 #endif
40 
41 namespace grpc_core {
42 
43 namespace {
44 class UrlTable : public BitSet<256> {
45  public:
46  GRPC_PCTENCODE_CONSTEXPR_FN UrlTable() {
47  for (int i = 'a'; i <= 'z'; i++) set(i);
48  for (int i = 'A'; i <= 'Z'; i++) set(i);
49  for (int i = '0'; i <= '9'; i++) set(i);
50  set('-');
51  set('_');
52  set('.');
53  set('~');
54  }
55 };
56 
57 GRPC_PCTENCODE_CONSTEXPR_VALUE UrlTable g_url_table;
58 
59 class CompatibleTable : public BitSet<256> {
60  public:
61  GRPC_PCTENCODE_CONSTEXPR_FN CompatibleTable() {
62  for (int i = 32; i <= 126; i++) {
63  if (i == '%') continue;
64  set(i);
65  }
66  }
67 };
68 
69 GRPC_PCTENCODE_CONSTEXPR_VALUE CompatibleTable g_compatible_table;
70 
71 // Map PercentEncodingType to a lookup table of legal symbols for that encoding.
72 const BitSet<256>& LookupTableForPercentEncodingType(PercentEncodingType type) {
73  switch (type) {
75  return g_url_table;
77  return g_compatible_table;
78  }
79  // Crash if a bad PercentEncodingType was passed in.
80  GPR_UNREACHABLE_CODE(abort());
81 }
82 } // namespace
83 
85  static const uint8_t hex[] = "0123456789ABCDEF";
86 
87  const BitSet<256>& lut = LookupTableForPercentEncodingType(type);
88 
89  // first pass: count the number of bytes needed to output this string
90  size_t output_length = 0;
91  bool any_reserved_bytes = false;
92  for (uint8_t c : slice) {
93  bool unres = lut.is_set(c);
94  output_length += unres ? 1 : 3;
95  any_reserved_bytes |= !unres;
96  }
97  // no unreserved bytes: return the string unmodified
98  if (!any_reserved_bytes) {
99  return slice;
100  }
101  // second pass: actually encode
102  auto out = MutableSlice::CreateUninitialized(output_length);
103  uint8_t* q = out.begin();
104  for (uint8_t c : slice) {
105  if (lut.is_set(c)) {
106  *q++ = c;
107  } else {
108  *q++ = '%';
109  *q++ = hex[c >> 4];
110  *q++ = hex[c & 15];
111  }
112  }
113  GPR_ASSERT(q == out.end());
114  return Slice(std::move(out));
115 }
116 
117 static bool ValidHex(const uint8_t* p, const uint8_t* end) {
118  if (p >= end) return false;
119  return (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') ||
120  (*p >= 'A' && *p <= 'F');
121 }
122 
123 static uint8_t DeHex(uint8_t c) {
124  if (c >= '0' && c <= '9') return static_cast<uint8_t>(c - '0');
125  if (c >= 'A' && c <= 'F') return static_cast<uint8_t>(c - 'A' + 10);
126  if (c >= 'a' && c <= 'f') return static_cast<uint8_t>(c - 'a' + 10);
127  GPR_UNREACHABLE_CODE(return 255);
128 }
129 
131  bool any_percent_encoded_stuff = false;
132  for (uint8_t c : slice_in) {
133  if (c == '%') {
134  any_percent_encoded_stuff = true;
135  break;
136  }
137  }
138  if (!any_percent_encoded_stuff) return slice_in;
139 
140  MutableSlice out = slice_in.TakeMutable();
141  uint8_t* q = out.begin();
142  const uint8_t* p = out.begin();
143  const uint8_t* end = out.end();
144  while (p != end) {
145  if (*p == '%') {
146  if (!ValidHex(p + 1, end) || !ValidHex(p + 2, end)) {
147  *q++ = *p++;
148  } else {
149  *q++ = static_cast<uint8_t>(DeHex(p[1]) << 4) | (DeHex(p[2]));
150  p += 3;
151  }
152  } else {
153  *q++ = *p++;
154  }
155  }
156  return Slice(out.TakeSubSlice(0, q - out.begin()));
157 }
158 
159 } // namespace grpc_core
grpc_core::PermissivePercentDecodeSlice
Slice PermissivePercentDecodeSlice(Slice slice_in)
Definition: percent_encoding.cc:130
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
log.h
grpc_core::PercentEncodingType::URL
@ URL
grpc_core
Definition: call_metric_recorder.h:31
grpc_core::Slice
Definition: src/core/lib/slice/slice.h:282
grpc_core::DeHex
static uint8_t DeHex(uint8_t c)
Definition: percent_encoding.cc:123
grpc_core::PercentEncodingType::Compatible
@ Compatible
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
GRPC_PCTENCODE_CONSTEXPR_FN
#define GRPC_PCTENCODE_CONSTEXPR_FN
Definition: percent_encoding.cc:37
grpc_core::BitSet::is_set
constexpr bool is_set(int i) const
Definition: bitset.h:112
grpc_core::MutableSlice::CreateUninitialized
static MutableSlice CreateUninitialized(size_t length)
Definition: src/core/lib/slice/slice.h:263
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
slice
grpc_slice slice
Definition: src/core/lib/surface/server.cc:467
grpc_core::PercentEncodingType
PercentEncodingType
Definition: percent_encoding.h:35
GPR_UNREACHABLE_CODE
#define GPR_UNREACHABLE_CODE(STATEMENT)
Definition: impl/codegen/port_platform.h:652
grpc_core::BitSet
Definition: bitset.h:85
grpc_core::ValidHex
static bool ValidHex(const uint8_t *p, const uint8_t *end)
Definition: percent_encoding.cc:117
percent_encoding.h
cpp.gmock_class.set
set
Definition: bloaty/third_party/googletest/googlemock/scripts/generator/cpp/gmock_class.py:44
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
grpc_core::MutableSlice
Definition: src/core/lib/slice/slice.h:244
GRPC_PCTENCODE_CONSTEXPR_VALUE
#define GRPC_PCTENCODE_CONSTEXPR_VALUE
Definition: percent_encoding.cc:38
grpc_core::PercentEncodeSlice
Slice PercentEncodeSlice(Slice slice, PercentEncodingType type)
Definition: percent_encoding.cc:84
bitset.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
port_platform.h


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:51