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 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 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 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 79 static void test_simple_encode_decode_b64_no_multiline(void) { 80 test_simple_encode_decode_b64(0, 0); 81 } 82 83 static void test_simple_encode_decode_b64_multiline(void) { 84 test_simple_encode_decode_b64(0, 1); 85 } 86 87 static void test_simple_encode_decode_b64_urlsafe_no_multiline(void) { 88 test_simple_encode_decode_b64(1, 0); 89 } 90 91 static void test_simple_encode_decode_b64_urlsafe_multiline(void) { 92 test_simple_encode_decode_b64(1, 1); 93 } 94 95 static void test_full_range_encode_decode_b64_no_multiline(void) { 96 test_full_range_encode_decode_b64(0, 0); 97 } 98 99 static void test_full_range_encode_decode_b64_multiline(void) { 100 test_full_range_encode_decode_b64(0, 1); 101 } 102 103 static void test_full_range_encode_decode_b64_urlsafe_no_multiline(void) { 104 test_full_range_encode_decode_b64(1, 0); 105 } 106 107 static void test_full_range_encode_decode_b64_urlsafe_multiline(void) { 108 test_full_range_encode_decode_b64(1, 1); 109 } 110 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 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 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 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