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