1 /*
2 *
3 * Copyright 2015 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 "src/core/lib/slice/b64.h"
20
21 #include <string.h>
22
23 #include <grpc/grpc.h>
24 #include <grpc/slice.h>
25 #include <grpc/support/alloc.h>
26 #include <grpc/support/log.h>
27 #include "src/core/lib/iomgr/exec_ctx.h"
28 #include "src/core/lib/slice/slice_internal.h"
29 #include "test/core/util/test_config.h"
30
buffers_are_equal(const unsigned char * buf1,const unsigned char * buf2,size_t size)31 static int buffers_are_equal(const unsigned char* buf1,
32 const unsigned char* buf2, size_t size) {
33 size_t i;
34 for (i = 0; i < size; i++) {
35 if (buf1[i] != buf2[i]) {
36 gpr_log(GPR_ERROR, "buf1 and buf2 differ: buf1[%d] = %x vs buf2[%d] = %x",
37 static_cast<int>(i), buf1[i], static_cast<int>(i), buf2[i]);
38 return 0;
39 }
40 }
41 return 1;
42 }
43
test_simple_encode_decode_b64(int url_safe,int multiline)44 static void test_simple_encode_decode_b64(int url_safe, int multiline) {
45 const char* hello = "hello";
46 char* hello_b64 =
47 grpc_base64_encode(hello, strlen(hello), url_safe, multiline);
48 grpc_core::ExecCtx exec_ctx;
49 grpc_slice hello_slice = grpc_base64_decode(hello_b64, url_safe);
50 GPR_ASSERT(GRPC_SLICE_LENGTH(hello_slice) == strlen(hello));
51 GPR_ASSERT(strncmp((const char*)GRPC_SLICE_START_PTR(hello_slice), hello,
52 GRPC_SLICE_LENGTH(hello_slice)) == 0);
53
54 grpc_slice_unref_internal(hello_slice);
55
56 gpr_free(hello_b64);
57 }
58
test_full_range_encode_decode_b64(int url_safe,int multiline)59 static void test_full_range_encode_decode_b64(int url_safe, int multiline) {
60 unsigned char orig[256];
61 size_t i;
62 char* b64;
63 grpc_slice orig_decoded;
64 for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
65
66 /* Try all the different paddings. */
67 for (i = 0; i < 3; i++) {
68 grpc_core::ExecCtx exec_ctx;
69 b64 = grpc_base64_encode(orig, sizeof(orig) - i, url_safe, multiline);
70 orig_decoded = grpc_base64_decode(b64, url_safe);
71 GPR_ASSERT(GRPC_SLICE_LENGTH(orig_decoded) == (sizeof(orig) - i));
72 GPR_ASSERT(buffers_are_equal(orig, GRPC_SLICE_START_PTR(orig_decoded),
73 sizeof(orig) - i));
74 grpc_slice_unref_internal(orig_decoded);
75 gpr_free(b64);
76 }
77 }
78
test_simple_encode_decode_b64_no_multiline(void)79 static void test_simple_encode_decode_b64_no_multiline(void) {
80 test_simple_encode_decode_b64(0, 0);
81 }
82
test_simple_encode_decode_b64_multiline(void)83 static void test_simple_encode_decode_b64_multiline(void) {
84 test_simple_encode_decode_b64(0, 1);
85 }
86
test_simple_encode_decode_b64_urlsafe_no_multiline(void)87 static void test_simple_encode_decode_b64_urlsafe_no_multiline(void) {
88 test_simple_encode_decode_b64(1, 0);
89 }
90
test_simple_encode_decode_b64_urlsafe_multiline(void)91 static void test_simple_encode_decode_b64_urlsafe_multiline(void) {
92 test_simple_encode_decode_b64(1, 1);
93 }
94
test_full_range_encode_decode_b64_no_multiline(void)95 static void test_full_range_encode_decode_b64_no_multiline(void) {
96 test_full_range_encode_decode_b64(0, 0);
97 }
98
test_full_range_encode_decode_b64_multiline(void)99 static void test_full_range_encode_decode_b64_multiline(void) {
100 test_full_range_encode_decode_b64(0, 1);
101 }
102
test_full_range_encode_decode_b64_urlsafe_no_multiline(void)103 static void test_full_range_encode_decode_b64_urlsafe_no_multiline(void) {
104 test_full_range_encode_decode_b64(1, 0);
105 }
106
test_full_range_encode_decode_b64_urlsafe_multiline(void)107 static void test_full_range_encode_decode_b64_urlsafe_multiline(void) {
108 test_full_range_encode_decode_b64(1, 1);
109 }
110
test_url_safe_unsafe_mismatch_failure(void)111 static void test_url_safe_unsafe_mismatch_failure(void) {
112 unsigned char orig[256];
113 size_t i;
114 char* b64;
115 grpc_slice orig_decoded;
116 int url_safe = 1;
117 for (i = 0; i < sizeof(orig); i++) orig[i] = static_cast<uint8_t>(i);
118
119 grpc_core::ExecCtx exec_ctx;
120 b64 = grpc_base64_encode(orig, sizeof(orig), url_safe, 0);
121 orig_decoded = grpc_base64_decode(b64, !url_safe);
122 GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded));
123 gpr_free(b64);
124 grpc_slice_unref_internal(orig_decoded);
125
126 b64 = grpc_base64_encode(orig, sizeof(orig), !url_safe, 0);
127 orig_decoded = grpc_base64_decode(b64, url_safe);
128 GPR_ASSERT(GRPC_SLICE_IS_EMPTY(orig_decoded));
129 gpr_free(b64);
130 grpc_slice_unref_internal(orig_decoded);
131 }
132
test_rfc4648_test_vectors(void)133 static void test_rfc4648_test_vectors(void) {
134 char* b64;
135
136 b64 = grpc_base64_encode("", 0, 0, 0);
137 GPR_ASSERT(strcmp("", b64) == 0);
138 gpr_free(b64);
139
140 b64 = grpc_base64_encode("f", 1, 0, 0);
141 GPR_ASSERT(strcmp("Zg==", b64) == 0);
142 gpr_free(b64);
143
144 b64 = grpc_base64_encode("fo", 2, 0, 0);
145 GPR_ASSERT(strcmp("Zm8=", b64) == 0);
146 gpr_free(b64);
147
148 b64 = grpc_base64_encode("foo", 3, 0, 0);
149 GPR_ASSERT(strcmp("Zm9v", b64) == 0);
150 gpr_free(b64);
151
152 b64 = grpc_base64_encode("foob", 4, 0, 0);
153 GPR_ASSERT(strcmp("Zm9vYg==", b64) == 0);
154 gpr_free(b64);
155
156 b64 = grpc_base64_encode("fooba", 5, 0, 0);
157 GPR_ASSERT(strcmp("Zm9vYmE=", b64) == 0);
158 gpr_free(b64);
159
160 b64 = grpc_base64_encode("foobar", 6, 0, 0);
161 GPR_ASSERT(strcmp("Zm9vYmFy", b64) == 0);
162 gpr_free(b64);
163 }
164
test_unpadded_decode(void)165 static void test_unpadded_decode(void) {
166 grpc_slice decoded;
167
168 grpc_core::ExecCtx exec_ctx;
169 decoded = grpc_base64_decode("Zm9vYmFy", 0);
170 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
171 GPR_ASSERT(grpc_slice_str_cmp(decoded, "foobar") == 0);
172 grpc_slice_unref(decoded);
173
174 decoded = grpc_base64_decode("Zm9vYmE", 0);
175 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
176 GPR_ASSERT(grpc_slice_str_cmp(decoded, "fooba") == 0);
177 grpc_slice_unref(decoded);
178
179 decoded = grpc_base64_decode("Zm9vYg", 0);
180 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
181 GPR_ASSERT(grpc_slice_str_cmp(decoded, "foob") == 0);
182 grpc_slice_unref(decoded);
183
184 decoded = grpc_base64_decode("Zm9v", 0);
185 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
186 GPR_ASSERT(grpc_slice_str_cmp(decoded, "foo") == 0);
187 grpc_slice_unref(decoded);
188
189 decoded = grpc_base64_decode("Zm8", 0);
190 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
191 GPR_ASSERT(grpc_slice_str_cmp(decoded, "fo") == 0);
192 grpc_slice_unref(decoded);
193
194 decoded = grpc_base64_decode("Zg", 0);
195 GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(decoded));
196 GPR_ASSERT(grpc_slice_str_cmp(decoded, "f") == 0);
197 grpc_slice_unref(decoded);
198
199 decoded = grpc_base64_decode("", 0);
200 GPR_ASSERT(GRPC_SLICE_IS_EMPTY(decoded));
201 }
202
main(int argc,char ** argv)203 int main(int argc, char** argv) {
204 grpc_test_init(argc, argv);
205 grpc_init();
206 test_simple_encode_decode_b64_no_multiline();
207 test_simple_encode_decode_b64_multiline();
208 test_simple_encode_decode_b64_urlsafe_no_multiline();
209 test_simple_encode_decode_b64_urlsafe_multiline();
210 test_full_range_encode_decode_b64_no_multiline();
211 test_full_range_encode_decode_b64_multiline();
212 test_full_range_encode_decode_b64_urlsafe_no_multiline();
213 test_full_range_encode_decode_b64_urlsafe_multiline();
214 test_url_safe_unsafe_mismatch_failure();
215 test_rfc4648_test_vectors();
216 test_unpadded_decode();
217 grpc_shutdown();
218 return 0;
219 }
220