summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-common/source/encoding.c
diff options
context:
space:
mode:
authorrobot-contrib <[email protected]>2025-05-14 06:53:03 +0300
committerrobot-contrib <[email protected]>2025-05-14 07:05:42 +0300
commit286dbc77293811055ff4f9303cd376eff9e50104 (patch)
treea50eea3eb2b824c7c68e15b4cc3e127731776d32 /contrib/restricted/aws/aws-c-common/source/encoding.c
parent0bf9db6399352012396e7791bcfd762e944b33c2 (diff)
Update contrib/restricted/aws/aws-c-common to 0.12.2
commit_hash:fc6e67f9b12b0b888c90bb97bf2b1cbfcd74a044
Diffstat (limited to 'contrib/restricted/aws/aws-c-common/source/encoding.c')
-rw-r--r--contrib/restricted/aws/aws-c-common/source/encoding.c57
1 files changed, 29 insertions, 28 deletions
diff --git a/contrib/restricted/aws/aws-c-common/source/encoding.c b/contrib/restricted/aws/aws-c-common/source/encoding.c
index bc860aa4b99..c9e14ee3b87 100644
--- a/contrib/restricted/aws/aws-c-common/source/encoding.c
+++ b/contrib/restricted/aws/aws-c-common/source/encoding.c
@@ -23,7 +23,7 @@ static inline size_t aws_common_private_base64_decode_sse41(const unsigned char
(void)out;
(void)len;
AWS_ASSERT(false);
- return (size_t)-1; /* unreachable */
+ return SIZE_MAX; /* unreachable */
}
static inline void aws_common_private_base64_encode_sse41(const unsigned char *in, unsigned char *out, size_t len) {
(void)in;
@@ -66,7 +66,9 @@ static const uint8_t BASE64_DECODING_TABLE[256] = {
int aws_hex_compute_encoded_len(size_t to_encode_len, size_t *encoded_length) {
AWS_ASSERT(encoded_length);
- size_t temp = (to_encode_len << 1) + 1;
+ /* For every byte of input, there will be 2 hex chars of encoded output */
+
+ size_t temp = to_encode_len << 1;
if (AWS_UNLIKELY(temp < to_encode_len)) {
return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
@@ -98,7 +100,7 @@ int aws_hex_encode(const struct aws_byte_cursor *AWS_RESTRICT to_encode, struct
output->buffer[written++] = HEX_CHARS[to_encode->ptr[i] & 0x0f];
}
- output->buffer[written] = '\0';
+ AWS_ASSERT(written == encoded_len);
output->len = encoded_len;
return AWS_OP_SUCCESS;
@@ -153,6 +155,10 @@ static int s_hex_decode_char_to_int(char character, uint8_t *int_val) {
int aws_hex_compute_decoded_len(size_t to_decode_len, size_t *decoded_len) {
AWS_ASSERT(decoded_len);
+ /* For every 2 hex chars (rounded up) of encoded input, there will be 1 byte of decoded output.
+ * Rounding is because if buffer isn't even, we'll pretend there's an extra '0' at start of buffer */
+
+ /* adding 1 before dividing by 2 is a trick to round up during division */
size_t temp = (to_decode_len + 1);
if (AWS_UNLIKELY(temp < to_decode_len)) {
@@ -212,6 +218,10 @@ int aws_hex_decode(const struct aws_byte_cursor *AWS_RESTRICT to_decode, struct
int aws_base64_compute_encoded_len(size_t to_encode_len, size_t *encoded_len) {
AWS_ASSERT(encoded_len);
+ /* For every 3 bytes (rounded up) of unencoded input, there will be 4 ascii characters of encoded output.
+ * Rounding is because the output will be padded with '=' chars if necessary to make it divisible by 4. */
+
+ /* adding 2 before dividing by 3 is a trick to round up during division */
size_t tmp = to_encode_len + 2;
if (AWS_UNLIKELY(tmp < to_encode_len)) {
@@ -220,7 +230,7 @@ int aws_base64_compute_encoded_len(size_t to_encode_len, size_t *encoded_len) {
tmp /= 3;
size_t overflow_check = tmp;
- tmp = 4 * tmp + 1; /* plus one for the NULL terminator */
+ tmp = 4 * tmp;
if (AWS_UNLIKELY(tmp < overflow_check)) {
return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
@@ -243,40 +253,40 @@ int aws_base64_compute_decoded_len(const struct aws_byte_cursor *AWS_RESTRICT to
return AWS_OP_SUCCESS;
}
+ /* ensure it's divisible by 4 */
if (AWS_UNLIKELY(len & 0x03)) {
return aws_raise_error(AWS_ERROR_INVALID_BASE64_STR);
}
- size_t tmp = len * 3;
-
- if (AWS_UNLIKELY(tmp < len)) {
- return aws_raise_error(AWS_ERROR_OVERFLOW_DETECTED);
- }
+ /* For every 4 ascii characters of encoded input, there will be 3 bytes of decoded output (deal with padding later)
+ * decoded_len = 3/4 * len <-- note that result will be smaller then len, so overflow can be avoided
+ * = (len / 4) * 3 <-- divide before multiply to avoid overflow
+ */
+ size_t decoded_len_tmp = (len / 4) * 3;
+ /* But last two ascii chars might be padding. */
+ AWS_ASSERT(len >= 4); /* we checked earlier len != 0, and was divisible by 4 */
size_t padding = 0;
-
- if (len >= 2 && input[len - 1] == '=' && input[len - 2] == '=') { /*last two chars are = */
+ if (input[len - 1] == '=' && input[len - 2] == '=') { /*last two chars are = */
padding = 2;
} else if (input[len - 1] == '=') { /*last char is = */
padding = 1;
}
- *decoded_len = (tmp / 4 - padding);
+ *decoded_len = decoded_len_tmp - padding;
return AWS_OP_SUCCESS;
}
int aws_base64_encode(const struct aws_byte_cursor *AWS_RESTRICT to_encode, struct aws_byte_buf *AWS_RESTRICT output) {
- AWS_ASSERT(to_encode->ptr);
- AWS_ASSERT(output->buffer);
+ AWS_ASSERT(to_encode->len == 0 || to_encode->ptr != NULL);
- size_t terminated_length = 0;
size_t encoded_length = 0;
- if (AWS_UNLIKELY(aws_base64_compute_encoded_len(to_encode->len, &terminated_length))) {
+ if (AWS_UNLIKELY(aws_base64_compute_encoded_len(to_encode->len, &encoded_length))) {
return AWS_OP_ERR;
}
size_t needed_capacity = 0;
- if (AWS_UNLIKELY(aws_add_size_checked(output->len, terminated_length, &needed_capacity))) {
+ if (AWS_UNLIKELY(aws_add_size_checked(output->len, encoded_length, &needed_capacity))) {
return AWS_OP_ERR;
}
@@ -284,16 +294,10 @@ int aws_base64_encode(const struct aws_byte_cursor *AWS_RESTRICT to_encode, stru
return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
}
- /*
- * For convenience to standard C functions expecting a null-terminated
- * string, the output is terminated. As the encoding itself can be used in
- * various ways, however, its length should never account for that byte.
- */
- encoded_length = (terminated_length - 1);
+ AWS_ASSERT(needed_capacity == 0 || output->buffer != NULL);
if (aws_common_private_has_avx2()) {
aws_common_private_base64_encode_sse41(to_encode->ptr, output->buffer + output->len, to_encode->len);
- output->buffer[output->len + encoded_length] = 0;
output->len += encoded_length;
return AWS_OP_SUCCESS;
}
@@ -329,9 +333,6 @@ int aws_base64_encode(const struct aws_byte_cursor *AWS_RESTRICT to_encode, stru
}
}
- /* it's a string add the null terminator. */
- output->buffer[output->len + encoded_length] = 0;
-
output->len += encoded_length;
return AWS_OP_SUCCESS;
@@ -361,7 +362,7 @@ int aws_base64_decode(const struct aws_byte_cursor *AWS_RESTRICT to_decode, stru
if (aws_common_private_has_avx2()) {
size_t result = aws_common_private_base64_decode_sse41(to_decode->ptr, output->buffer, to_decode->len);
- if (result == -1) {
+ if (result == SIZE_MAX) {
return aws_raise_error(AWS_ERROR_INVALID_BASE64_STR);
}