diff options
-rw-r--r-- | src/core/ext/transport/chttp2/transport/bin_decoder.cc | 12 | ||||
-rw-r--r-- | src/core/ext/transport/chttp2/transport/bin_decoder.h | 2 | ||||
-rw-r--r-- | test/core/transport/chttp2/bin_decoder_test.cc | 30 |
3 files changed, 41 insertions, 3 deletions
diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.cc b/src/core/ext/transport/chttp2/transport/bin_decoder.cc index 53b8622259..831a36961e 100644 --- a/src/core/ext/transport/chttp2/transport/bin_decoder.cc +++ b/src/core/ext/transport/chttp2/transport/bin_decoder.cc @@ -75,12 +75,20 @@ static bool input_is_valid(uint8_t* input_ptr, size_t length) { #define COMPOSE_OUTPUT_BYTE_2(input_ptr) \ (uint8_t)((decode_table[input_ptr[2]] << 6) | decode_table[input_ptr[3]]) -size_t grpc_base64_infer_length_after_decode(const grpc_slice& slice) { +// By RFC 4648, if the length of the encoded string without padding is 4n+r, +// the length of decoded string is: 1) 3n if r = 0, 2) 3n + 1 if r = 2, 3, or +// 3) invalid if r = 1. +size_t grpc_chttp2_base64_infer_length_after_decode(const grpc_slice& slice) { size_t len = GRPC_SLICE_LENGTH(slice); const uint8_t* bytes = GRPC_SLICE_START_PTR(slice); while (len > 0 && bytes[len - 1] == '=') { len--; } + if (GRPC_SLICE_LENGTH(slice) - len > 2) { + gpr_log(GPR_ERROR, + "Base64 decoding failed. Input has more than 2 paddings."); + return 0; + } size_t tuples = len / 4; size_t tail_case = len % 4; if (tail_case == 1) { @@ -88,7 +96,7 @@ size_t grpc_base64_infer_length_after_decode(const grpc_slice& slice) { "Base64 decoding failed. Input has a length of %zu (without" " padding), which is invalid.\n", len); - tail_case = 0; + return 0; } return tuples * 3 + tail_xtra[tail_case]; } diff --git a/src/core/ext/transport/chttp2/transport/bin_decoder.h b/src/core/ext/transport/chttp2/transport/bin_decoder.h index b5acb3fa91..a0d74fb20d 100644 --- a/src/core/ext/transport/chttp2/transport/bin_decoder.h +++ b/src/core/ext/transport/chttp2/transport/bin_decoder.h @@ -49,6 +49,6 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_slice input, size_t output_length); /* Infer the length of decoded data from encoded data. */ -size_t grpc_base64_infer_length_after_decode(const grpc_slice& slice); +size_t grpc_chttp2_base64_infer_length_after_decode(const grpc_slice& slice); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_DECODER_H */ diff --git a/test/core/transport/chttp2/bin_decoder_test.cc b/test/core/transport/chttp2/bin_decoder_test.cc index 283eebbacf..751dd90c8c 100644 --- a/test/core/transport/chttp2/bin_decoder_test.cc +++ b/test/core/transport/chttp2/bin_decoder_test.cc @@ -67,6 +67,16 @@ static grpc_slice base64_decode_with_length(const char* s, return out; } +static size_t base64_infer_length(const char* s) { + grpc_slice ss = grpc_slice_from_copied_string(s); + size_t out = grpc_chttp2_base64_infer_length_after_decode(ss); + grpc_slice_unref_internal(ss); + return out; +} + +#define EXPECT_DECODED_LENGTH(s, expected) \ + GPR_ASSERT((expected) == base64_infer_length((s))); + #define EXPECT_SLICE_EQ(expected, slice) \ expect_slice_eq( \ grpc_slice_from_copied_buffer(expected, sizeof(expected) - 1), slice, \ @@ -131,6 +141,26 @@ int main(int argc, char** argv) { // Test illegal charactors in grpc_chttp2_base64_decode_with_length EXPECT_SLICE_EQ("", base64_decode_with_length("Zm:v", 3)); EXPECT_SLICE_EQ("", base64_decode_with_length("Zm=v", 3)); + + EXPECT_DECODED_LENGTH("", 0); + EXPECT_DECODED_LENGTH("ab", 1); + EXPECT_DECODED_LENGTH("abc", 2); + EXPECT_DECODED_LENGTH("abcd", 3); + EXPECT_DECODED_LENGTH("abcdef", 4); + EXPECT_DECODED_LENGTH("abcdefg", 5); + EXPECT_DECODED_LENGTH("abcdefgh", 6); + + EXPECT_DECODED_LENGTH("ab==", 1); + EXPECT_DECODED_LENGTH("abc=", 2); + EXPECT_DECODED_LENGTH("abcd", 3); + EXPECT_DECODED_LENGTH("abcdef==", 4); + EXPECT_DECODED_LENGTH("abcdefg=", 5); + EXPECT_DECODED_LENGTH("abcdefgh", 6); + + EXPECT_DECODED_LENGTH("a", 0); + EXPECT_DECODED_LENGTH("a===", 0); + EXPECT_DECODED_LENGTH("abcde", 0); + EXPECT_DECODED_LENGTH("abcde===", 0); } grpc_shutdown(); return all_ok ? 0 : 1; |