File CVE-2024-21646.patch of Package python-uamqp.32584
From 74c02ad54ae987ccd7a51c676581c7d4a40127ba Mon Sep 17 00:00:00 2001
From: Kashif Khan <361477+kashifkhan@users.noreply.github.com>
Date: Mon, 22 Jan 2024 09:11:42 -0600
Subject: [PATCH] CVE fix (#373)
* Fixes for CVE-2024-21646
* changelog update
* add back function
* fix windows build
* move install for windows compiler
---
.../azure-c-shared-utility/CMakeLists.txt | 1 +
.../inc/azure_c_shared_utility/safe_math.h | 17 +++
src/vendor/azure-uamqp-c/src/amqpvalue.c | 136 ++++++++++++++----
3 files changed, 130 insertions(+), 24 deletions(-)
create mode 100644 src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/inc/azure_c_shared_utility/safe_math.h
diff --git a/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/CMakeLists.txt b/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/CMakeLists.txt
index 5101951..c2f9b2f 100644
--- a/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/CMakeLists.txt
+++ b/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/CMakeLists.txt
@@ -373,6 +373,7 @@ set(source_h_files
./inc/azure_c_shared_utility/tlsio.h
./inc/azure_c_shared_utility/optionhandler.h
./inc/azure_c_shared_utility/memory_data.h
+ ./inc/azure_c_shared_utility/safe_math.h
${LOGGING_STACKTRACE_H_FILE}
)
diff --git a/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/inc/azure_c_shared_utility/safe_math.h b/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/inc/azure_c_shared_utility/safe_math.h
new file mode 100644
index 0000000..cf8198d
--- /dev/null
+++ b/src/vendor/azure-uamqp-c/deps/azure-c-shared-utility/inc/azure_c_shared_utility/safe_math.h
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef SAFE_MATH_H
+#define SAFE_MATH_H
+
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)((size_t)~(size_t)0))
+#endif
+
+#define safe_add_size_t(a, b) ((((size_t)(a)) < ((size_t)(SIZE_MAX - ((size_t)(b))))) ? ((size_t)(a) + (size_t)(b)) : SIZE_MAX)
+
+#define safe_subtract_size_t(a, b) (((a) >= (b)) ? ((size_t)(a) - (size_t)(b)) : SIZE_MAX)
+
+#define safe_multiply_size_t(a, b) (((a) == 0 || (b) == 0) ? 0 : (((SIZE_MAX / (size_t)(a)) >= (size_t)(b)) ? (size_t)(a) * (size_t)(b) : SIZE_MAX))
+
+#endif // SAFE_MATH_H
\ No newline at end of file
diff --git a/src/vendor/azure-uamqp-c/src/amqpvalue.c b/src/vendor/azure-uamqp-c/src/amqpvalue.c
index e1445e7..43245cf 100644
--- a/src/vendor/azure-uamqp-c/src/amqpvalue.c
+++ b/src/vendor/azure-uamqp-c/src/amqpvalue.c
@@ -11,6 +11,7 @@
#include "azure_uamqp_c/amqp_types.h"
#include "azure_uamqp_c/amqpvalue.h"
#include "azure_c_shared_utility/refcount.h"
+#include "azure_c_shared_utility/safe_math.h"
// max alloc size 100MB
#define MAX_AMQPVALUE_MALLOC_SIZE_BYTES (100 * 1024 * 1024)
@@ -1069,8 +1070,20 @@ AMQP_VALUE amqpvalue_create_string(const char* value)
else
{
size_t length = strlen(value);
+ size_t malloc_size = length + 1;
+
+ // If the result of malloc_size is zero it means it had a type overflow (size_t is an unsigned type).
+ // It is very unlikely but could happen.
+ if (malloc_size == 0)
+ {
+ LogError("Invalid string size exceeded max allocation");
+ result = NULL;
+ }
+ else
+ {
+ result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA);
+ }
- result = REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA);
if (result == NULL)
{
/* Codes_SRS_AMQPVALUE_01_136: [If allocating the AMQP_VALUE fails then amqpvalue_create_string shall return NULL.] */
@@ -1079,7 +1092,7 @@ AMQP_VALUE amqpvalue_create_string(const char* value)
else
{
result->type = AMQP_TYPE_STRING;
- result->value.string_value.chars = (char*)malloc(length + 1);
+ result->value.string_value.chars = (char*)malloc(malloc_size);
if (result->value.string_value.chars == NULL)
{
/* Codes_SRS_AMQPVALUE_01_136: [If allocating the AMQP_VALUE fails then amqpvalue_create_string shall return NULL.] */
@@ -1089,7 +1102,7 @@ AMQP_VALUE amqpvalue_create_string(const char* value)
}
else
{
- (void)memcpy(result->value.string_value.chars, value, length + 1);
+ (void)memcpy(result->value.string_value.chars, value, malloc_size);
}
}
}
@@ -1145,7 +1158,7 @@ AMQP_VALUE amqpvalue_create_symbol(const char* value)
else
{
size_t length = strlen(value);
- if (length > UINT32_MAX)
+ if (length >= UINT32_MAX)
{
/* Codes_SRS_AMQPVALUE_01_401: [ If the string pointed to by value is longer than 2^32-1 then amqpvalue_create_symbol shall return NULL. ]*/
LogError("string too long to be represented as a symbol");
@@ -1402,7 +1415,7 @@ int amqpvalue_set_list_item(AMQP_VALUE value, uint32_t index, AMQP_VALUE list_it
{
if (index >= value_data->value.list_value.count)
{
- AMQP_VALUE* new_list = (AMQP_VALUE*)realloc(value_data->value.list_value.items, (index + 1) * sizeof(AMQP_VALUE));
+ AMQP_VALUE* new_list = (AMQP_VALUE*)realloc(value_data->value.list_value.items, ((size_t)index + 1) * sizeof(AMQP_VALUE));
if (new_list == NULL)
{
/* Codes_SRS_AMQPVALUE_01_170: [When amqpvalue_set_list_item fails due to not being able to clone the item or grow the list, the list shall not be altered.] */
@@ -1629,7 +1642,7 @@ int amqpvalue_set_map_value(AMQP_VALUE map, AMQP_VALUE key, AMQP_VALUE value)
}
else
{
- AMQP_MAP_KEY_VALUE_PAIR* new_pairs = (AMQP_MAP_KEY_VALUE_PAIR*)realloc(value_data->value.map_value.pairs, (value_data->value.map_value.pair_count + 1) * sizeof(AMQP_MAP_KEY_VALUE_PAIR));
+ AMQP_MAP_KEY_VALUE_PAIR* new_pairs = (AMQP_MAP_KEY_VALUE_PAIR*)realloc(value_data->value.map_value.pairs, ((size_t)value_data->value.map_value.pair_count + 1) * sizeof(AMQP_MAP_KEY_VALUE_PAIR));
if (new_pairs == NULL)
{
/* Codes_SRS_AMQPVALUE_01_186: [If allocating memory to hold a new key/value pair fails, amqpvalue_set_map_value shall fail and return a non-zero value.] */
@@ -1934,7 +1947,7 @@ int amqpvalue_add_array_item(AMQP_VALUE value, AMQP_VALUE array_item_value)
}
else
{
- AMQP_VALUE* new_array = (AMQP_VALUE*)realloc(value_data->value.array_value.items, (value_data->value.array_value.count + 1) * sizeof(AMQP_VALUE));
+ AMQP_VALUE* new_array = (AMQP_VALUE*)realloc(value_data->value.array_value.items, ((size_t)value_data->value.array_value.count + 1) * sizeof(AMQP_VALUE));
if (new_array == NULL)
{
/* Codes_SRS_AMQPVALUE_01_423: [ When `amqpvalue_add_array_item` fails due to not being able to clone the item or grow the array, the array shall not be altered. ] */
@@ -5902,7 +5915,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_to_value->value.binary_value.length + 1)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_to_value->value.binary_value.length + 1)
{
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
@@ -5941,7 +5954,17 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
}
else
{
- internal_decoder_data->decode_to_value->value.binary_value.bytes = (unsigned char*)malloc((size_t)internal_decoder_data->decode_to_value->value.binary_value.length + 1);
+ size_t malloc_size = (size_t)internal_decoder_data->decode_to_value->value.binary_value.length + 1;
+ if (malloc_size == 0)
+ {
+ internal_decoder_data->decode_to_value->value.binary_value.bytes = NULL;
+ LogError("Invalid binary_value size exceeded max allocation");
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.binary_value.bytes = (unsigned char*)malloc(malloc_size);
+ }
+
if (internal_decoder_data->decode_to_value->value.binary_value.bytes == NULL)
{
/* Codes_SRS_AMQPVALUE_01_326: [If any allocation failure occurs during decoding, amqpvalue_decode_bytes shall fail and return a non-zero value.] */
@@ -5973,7 +5996,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_to_value->value.binary_value.length + 4)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_to_value->value.binary_value.length + 4)
{
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
internal_decoder_data->on_value_decoded(internal_decoder_data->on_value_decoded_context, internal_decoder_data->decode_to_value);
@@ -5994,7 +6017,19 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
buffer++;
size--;
- internal_decoder_data->decode_to_value->value.string_value.chars = (char*)malloc(internal_decoder_data->decode_value_state.string_value_state.length + 1);
+ size_t malloc_size = (size_t)internal_decoder_data->decode_value_state.string_value_state.length + 1;
+ // If the result of malloc_size is zero it means it had a type overflow (size_t is an unsigned type).
+ // It is very unlikely but could happen.
+ if (malloc_size == 0)
+ {
+ internal_decoder_data->decode_to_value->value.string_value.chars = NULL;
+ LogError("Invalid string size exceeded max allocation");
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.string_value.chars = (char*)malloc(malloc_size);
+ }
+
if (internal_decoder_data->decode_to_value->value.string_value.chars == NULL)
{
/* Codes_SRS_AMQPVALUE_01_326: [If any allocation failure occurs during decoding, amqpvalue_decode_bytes shall fail and return a non-zero value.] */
@@ -6030,7 +6065,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_value_state.string_value_state.length + 1)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_value_state.string_value_state.length + 1)
{
internal_decoder_data->decode_to_value->value.string_value.chars[internal_decoder_data->decode_value_state.string_value_state.length] = 0;
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
@@ -6057,7 +6092,19 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
if (internal_decoder_data->bytes_decoded == 4)
{
- internal_decoder_data->decode_to_value->value.string_value.chars = (char*)malloc((size_t)internal_decoder_data->decode_value_state.string_value_state.length + 1);
+ size_t malloc_size = (size_t)internal_decoder_data->decode_value_state.string_value_state.length + 1;
+ // If the result of malloc_size is zero it means it had a type overflow (size_t is an unsigned type).
+ // It is very unlikely but could happen.
+ if (malloc_size == 0)
+ {
+ internal_decoder_data->decode_to_value->value.string_value.chars = NULL;
+ LogError("Invalid string value size exceeded max allocation");
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.string_value.chars = (char*)malloc(malloc_size);
+ }
+
if (internal_decoder_data->decode_to_value->value.string_value.chars == NULL)
{
/* Codes_SRS_AMQPVALUE_01_326: [If any allocation failure occurs during decoding, amqpvalue_decode_bytes shall fail and return a non-zero value.] */
@@ -6098,7 +6145,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_value_state.string_value_state.length + 4)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_value_state.string_value_state.length + 4)
{
internal_decoder_data->decode_to_value->value.string_value.chars[internal_decoder_data->decode_value_state.string_value_state.length] = '\0';
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
@@ -6123,7 +6170,19 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
buffer++;
size--;
- internal_decoder_data->decode_to_value->value.symbol_value.chars = (char*)malloc(internal_decoder_data->decode_value_state.symbol_value_state.length + 1);
+ size_t malloc_size = (size_t)internal_decoder_data->decode_value_state.symbol_value_state.length + 1;
+ // If the result of malloc_size is zero it means it had a type overflow (size_t is an unsigned type).
+ // It is very unlikely but could happen.
+ if (malloc_size == 0)
+ {
+ internal_decoder_data->decode_to_value->value.symbol_value.chars = NULL;
+ LogError("Invalid symbol_value size exceeded max allocation");
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.symbol_value.chars = (char*)malloc(malloc_size);
+ }
+
if (internal_decoder_data->decode_to_value->value.symbol_value.chars == NULL)
{
/* Codes_SRS_AMQPVALUE_01_326: [If any allocation failure occurs during decoding, amqpvalue_decode_bytes shall fail and return a non-zero value.] */
@@ -6159,7 +6218,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_value_state.symbol_value_state.length + 1)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_value_state.symbol_value_state.length + 1)
{
internal_decoder_data->decode_to_value->value.symbol_value.chars[internal_decoder_data->decode_value_state.symbol_value_state.length] = 0;
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
@@ -6186,7 +6245,19 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
if (internal_decoder_data->bytes_decoded == 4)
{
- internal_decoder_data->decode_to_value->value.symbol_value.chars = (char*)malloc((size_t)internal_decoder_data->decode_value_state.symbol_value_state.length + 1);
+ size_t malloc_size = (size_t)internal_decoder_data->decode_value_state.symbol_value_state.length + 1;
+ // If the result of malloc_size is zero it means it had a type overflow (size_t is an unsigned type).
+ // It is very unlikely but could happen.
+ if (malloc_size == 0)
+ {
+ internal_decoder_data->decode_to_value->value.symbol_value.chars = NULL;
+ LogError("Invalid symbol value size exceeded max allocation");
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.symbol_value.chars = (char*)malloc(malloc_size);
+ }
+
if (internal_decoder_data->decode_to_value->value.symbol_value.chars == NULL)
{
/* Codes_SRS_AMQPVALUE_01_326: [If any allocation failure occurs during decoding, amqpvalue_decode_bytes shall fail and return a non-zero value.] */
@@ -6227,7 +6298,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
size -= to_copy;
internal_decoder_data->bytes_decoded += to_copy;
- if (internal_decoder_data->bytes_decoded == internal_decoder_data->decode_value_state.symbol_value_state.length + 4)
+ if (internal_decoder_data->bytes_decoded == (size_t)internal_decoder_data->decode_value_state.symbol_value_state.length + 4)
{
internal_decoder_data->decode_to_value->value.symbol_value.chars[internal_decoder_data->decode_value_state.symbol_value_state.length] = '\0';
internal_decoder_data->decoder_state = DECODER_STATE_CONSTRUCTOR;
@@ -6530,8 +6601,19 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
uint32_t i;
internal_decoder_data->decode_to_value->value.map_value.pair_count /= 2;
+ size_t malloc_size = safe_multiply_size_t(sizeof(AMQP_MAP_KEY_VALUE_PAIR), (size_t)internal_decoder_data->decode_to_value->value.map_value.pair_count);
+ malloc_size = safe_multiply_size_t(malloc_size, 2);
+
+ if (malloc_size == SIZE_MAX)
+ {
+ LogError("Invalid map_value size exceeded max allocation");
+ internal_decoder_data->decode_to_value->value.map_value.pairs = NULL;
+ }
+ else
+ {
+ internal_decoder_data->decode_to_value->value.map_value.pairs = (AMQP_MAP_KEY_VALUE_PAIR*)malloc(malloc_size);
+ }
- internal_decoder_data->decode_to_value->value.map_value.pairs = (AMQP_MAP_KEY_VALUE_PAIR*)malloc(sizeof(AMQP_MAP_KEY_VALUE_PAIR) * (internal_decoder_data->decode_to_value->value.map_value.pair_count * 2));
if (internal_decoder_data->decode_to_value->value.map_value.pairs == NULL)
{
LogError("Could not allocate memory for map value items");
@@ -6569,13 +6651,21 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
uint32_t i;
internal_decoder_data->decode_to_value->value.map_value.pair_count /= 2;
+ size_t malloc_size = safe_multiply_size_t((size_t)internal_decoder_data->decode_to_value->value.map_value.pair_count, 2);
+ malloc_size = safe_multiply_size_t(sizeof(AMQP_MAP_KEY_VALUE_PAIR), malloc_size);
+
if (internal_decoder_data->decode_to_value->value.map_value.pair_count > MAX_AMQPVALUE_ITEM_COUNT)
{
LogError("AMQP list map count exceeded MAX_AMQPVALUE_ITEM_COUNT");
result = MU_FAILURE;
}
+ else if (malloc_size == SIZE_MAX)
+ {
+ LogError("Invalid map_value size exceeded max allocation");
+ result = MU_FAILURE;
+ }
else if ((internal_decoder_data->decode_to_value->value.map_value.pairs =
- (AMQP_MAP_KEY_VALUE_PAIR*)malloc(sizeof(AMQP_MAP_KEY_VALUE_PAIR) * (internal_decoder_data->decode_to_value->value.map_value.pair_count * 2)))
+ (AMQP_MAP_KEY_VALUE_PAIR*)malloc(malloc_size))
== NULL)
{
LogError("Could not allocate memory for map value items");
@@ -6610,8 +6700,6 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
if (internal_decoder_data->bytes_decoded == 0)
{
- AMQP_VALUE_DATA* map_item;
-
if (internal_decoder_data->decode_value_state.map_value_state.item >= internal_decoder_data->decode_to_value->value.map_value.pair_count)
{
LogError("Map item index is out of range");
@@ -6620,7 +6708,7 @@ static int internal_decoder_decode_bytes(INTERNAL_DECODER_DATA* internal_decoder
break;
}
- map_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA);
+ AMQP_VALUE_DATA* map_item = (AMQP_VALUE_DATA*)REFCOUNT_TYPE_CREATE(AMQP_VALUE_DATA);
if (map_item == NULL)
{
LogError("Could not allocate memory for map item");
@@ -7382,4 +7470,4 @@ AMQP_VALUE amqpvalue_get_list_item_in_place(AMQP_VALUE value, size_t index)
}
return result;
-}
+}
\ No newline at end of file
--
2.43.0