• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 #include <grpc/support/port_platform.h>
20 
21 #include "src/core/lib/slice/percent_encoding.h"
22 
23 #include <grpc/support/log.h>
24 
25 #include "src/core/lib/slice/slice_internal.h"
26 
27 const uint8_t grpc_url_percent_encoding_unreserved_bytes[256 / 8] = {
28     0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0xfe, 0xff, 0xff,
29     0x87, 0xfe, 0xff, 0xff, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
31 const uint8_t grpc_compatible_percent_encoding_unreserved_bytes[256 / 8] = {
32     0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33     0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
35 
is_unreserved_character(uint8_t c,const uint8_t * unreserved_bytes)36 static bool is_unreserved_character(uint8_t c,
37                                     const uint8_t* unreserved_bytes) {
38   return ((unreserved_bytes[c / 8] >> (c % 8)) & 1) != 0;
39 }
40 
grpc_percent_encode_slice(grpc_slice slice,const uint8_t * unreserved_bytes)41 grpc_slice grpc_percent_encode_slice(grpc_slice slice,
42                                      const uint8_t* unreserved_bytes) {
43   static const uint8_t hex[] = "0123456789ABCDEF";
44 
45   // first pass: count the number of bytes needed to output this string
46   size_t output_length = 0;
47   const uint8_t* slice_start = GRPC_SLICE_START_PTR(slice);
48   const uint8_t* slice_end = GRPC_SLICE_END_PTR(slice);
49   const uint8_t* p;
50   bool any_reserved_bytes = false;
51   for (p = slice_start; p < slice_end; p++) {
52     bool unres = is_unreserved_character(*p, unreserved_bytes);
53     output_length += unres ? 1 : 3;
54     any_reserved_bytes |= !unres;
55   }
56   // no unreserved bytes: return the string unmodified
57   if (!any_reserved_bytes) {
58     return grpc_slice_ref_internal(slice);
59   }
60   // second pass: actually encode
61   grpc_slice out = GRPC_SLICE_MALLOC(output_length);
62   uint8_t* q = GRPC_SLICE_START_PTR(out);
63   for (p = slice_start; p < slice_end; p++) {
64     if (is_unreserved_character(*p, unreserved_bytes)) {
65       *q++ = *p;
66     } else {
67       *q++ = '%';
68       *q++ = hex[*p >> 4];
69       *q++ = hex[*p & 15];
70     }
71   }
72   GPR_ASSERT(q == GRPC_SLICE_END_PTR(out));
73   return out;
74 }
75 
valid_hex(const uint8_t * p,const uint8_t * end)76 static bool valid_hex(const uint8_t* p, const uint8_t* end) {
77   if (p >= end) return false;
78   return (*p >= '0' && *p <= '9') || (*p >= 'a' && *p <= 'f') ||
79          (*p >= 'A' && *p <= 'F');
80 }
81 
dehex(uint8_t c)82 static uint8_t dehex(uint8_t c) {
83   if (c >= '0' && c <= '9') return static_cast<uint8_t>(c - '0');
84   if (c >= 'A' && c <= 'F') return static_cast<uint8_t>(c - 'A' + 10);
85   if (c >= 'a' && c <= 'f') return static_cast<uint8_t>(c - 'a' + 10);
86   GPR_UNREACHABLE_CODE(return 255);
87 }
88 
grpc_strict_percent_decode_slice(grpc_slice slice_in,const uint8_t * unreserved_bytes,grpc_slice * slice_out)89 bool grpc_strict_percent_decode_slice(grpc_slice slice_in,
90                                       const uint8_t* unreserved_bytes,
91                                       grpc_slice* slice_out) {
92   const uint8_t* p = GRPC_SLICE_START_PTR(slice_in);
93   const uint8_t* in_end = GRPC_SLICE_END_PTR(slice_in);
94   size_t out_length = 0;
95   bool any_percent_encoded_stuff = false;
96   while (p != in_end) {
97     if (*p == '%') {
98       if (!valid_hex(++p, in_end)) return false;
99       if (!valid_hex(++p, in_end)) return false;
100       p++;
101       out_length++;
102       any_percent_encoded_stuff = true;
103     } else if (is_unreserved_character(*p, unreserved_bytes)) {
104       p++;
105       out_length++;
106     } else {
107       return false;
108     }
109   }
110   if (!any_percent_encoded_stuff) {
111     *slice_out = grpc_slice_ref_internal(slice_in);
112     return true;
113   }
114   p = GRPC_SLICE_START_PTR(slice_in);
115   *slice_out = GRPC_SLICE_MALLOC(out_length);
116   uint8_t* q = GRPC_SLICE_START_PTR(*slice_out);
117   while (p != in_end) {
118     if (*p == '%') {
119       *q++ = static_cast<uint8_t>(dehex(p[1]) << 4) | (dehex(p[2]));
120       p += 3;
121     } else {
122       *q++ = *p++;
123     }
124   }
125   GPR_ASSERT(q == GRPC_SLICE_END_PTR(*slice_out));
126   return true;
127 }
128 
grpc_permissive_percent_decode_slice(grpc_slice slice_in)129 grpc_slice grpc_permissive_percent_decode_slice(grpc_slice slice_in) {
130   const uint8_t* p = GRPC_SLICE_START_PTR(slice_in);
131   const uint8_t* in_end = GRPC_SLICE_END_PTR(slice_in);
132   size_t out_length = 0;
133   bool any_percent_encoded_stuff = false;
134   while (p != in_end) {
135     if (*p == '%') {
136       if (!valid_hex(p + 1, in_end) || !valid_hex(p + 2, in_end)) {
137         p++;
138         out_length++;
139       } else {
140         p += 3;
141         out_length++;
142         any_percent_encoded_stuff = true;
143       }
144     } else {
145       p++;
146       out_length++;
147     }
148   }
149   if (!any_percent_encoded_stuff) {
150     return grpc_slice_ref_internal(slice_in);
151   }
152   p = GRPC_SLICE_START_PTR(slice_in);
153   grpc_slice out = GRPC_SLICE_MALLOC(out_length);
154   uint8_t* q = GRPC_SLICE_START_PTR(out);
155   while (p != in_end) {
156     if (*p == '%') {
157       if (!valid_hex(p + 1, in_end) || !valid_hex(p + 2, in_end)) {
158         *q++ = *p++;
159       } else {
160         *q++ = static_cast<uint8_t>(dehex(p[1]) << 4) | (dehex(p[2]));
161         p += 3;
162       }
163     } else {
164       *q++ = *p++;
165     }
166   }
167   GPR_ASSERT(q == GRPC_SLICE_END_PTR(out));
168   return out;
169 }
170