diff options
author | robot-contrib <[email protected]> | 2025-05-14 06:53:03 +0300 |
---|---|---|
committer | robot-contrib <[email protected]> | 2025-05-14 07:05:42 +0300 |
commit | 286dbc77293811055ff4f9303cd376eff9e50104 (patch) | |
tree | a50eea3eb2b824c7c68e15b4cc3e127731776d32 /contrib/restricted/aws/aws-c-common/source | |
parent | 0bf9db6399352012396e7791bcfd762e944b33c2 (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')
66 files changed, 7355 insertions, 389 deletions
diff --git a/contrib/restricted/aws/aws-c-common/source/allocator.c b/contrib/restricted/aws/aws-c-common/source/allocator.c index d3d1e98bd72..71f7a64b0b3 100644 --- a/contrib/restricted/aws/aws-c-common/source/allocator.c +++ b/contrib/restricted/aws/aws-c-common/source/allocator.c @@ -207,7 +207,7 @@ void *aws_mem_calloc(struct aws_allocator *allocator, size_t num, size_t size) { return mem; } -#define AWS_ALIGN_ROUND_UP(value, alignment) (((value) + ((alignment)-1)) & ~((alignment)-1)) +#define AWS_ALIGN_ROUND_UP(value, alignment) (((value) + ((alignment) - 1)) & ~((alignment) - 1)) void *aws_mem_acquire_many(struct aws_allocator *allocator, size_t count, ...) { diff --git a/contrib/restricted/aws/aws-c-common/source/arch/intel/asm/cpuid.c b/contrib/restricted/aws/aws-c-common/source/arch/intel/asm/cpuid.c index d2ceab01060..93657460e63 100644 --- a/contrib/restricted/aws/aws-c-common/source/arch/intel/asm/cpuid.c +++ b/contrib/restricted/aws/aws-c-common/source/arch/intel/asm/cpuid.c @@ -27,3 +27,14 @@ void aws_run_cpuid(uint32_t eax, uint32_t ecx, uint32_t *abcd) { abcd[2] = ecx; abcd[3] = edx; } + +uint64_t aws_run_xgetbv(uint32_t xcr) { + /* NOTE: we could have used the _xgetbv() intrinsic in <immintrin.h>, but it's missing from GCC < 9.0: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71659 */ + + /* xgetbv writes high and low of 64bit value to EDX:EAX */ + uint32_t xcrhigh; + uint32_t xcrlow; + __asm__ __volatile__("xgetbv" : "=a"(xcrlow), "=d"(xcrhigh) : "c"(xcr)); + return (((uint64_t)xcrhigh) << 32) | xcrlow; +} diff --git a/contrib/restricted/aws/aws-c-common/source/arch/intel/cpuid.c b/contrib/restricted/aws/aws-c-common/source/arch/intel/cpuid.c index 465fccd17a5..e50fa2cdf3d 100644 --- a/contrib/restricted/aws/aws-c-common/source/arch/intel/cpuid.c +++ b/contrib/restricted/aws/aws-c-common/source/arch/intel/cpuid.c @@ -13,57 +13,69 @@ #include <stdlib.h> extern void aws_run_cpuid(uint32_t eax, uint32_t ecx, uint32_t *abcd); +extern uint64_t aws_run_xgetbv(uint32_t xcr); -typedef bool(has_feature_fn)(void); +static bool s_cpu_features[AWS_CPU_FEATURE_COUNT]; +static bool s_cpu_features_cached; -static bool s_has_clmul(void) { +static void s_cache_cpu_features(void) { + /*************************************************************************** + * First, find the max EAX value we can pass to CPUID without undefined behavior + * https://en.wikipedia.org/w/index.php?title=CPUID&oldid=1270569388#EAX=0:_Highest_Function_Parameter_and_Manufacturer_ID + **************************************************************************/ uint32_t abcd[4]; - uint32_t clmul_mask = 0x00000002; - aws_run_cpuid(1, 0, abcd); - - if ((abcd[2] & clmul_mask) != clmul_mask) - return false; - - return true; -} - -static bool s_has_sse41(void) { - uint32_t abcd[4]; - uint32_t sse41_mask = 0x00080000; - aws_run_cpuid(1, 0, abcd); - - if ((abcd[2] & sse41_mask) != sse41_mask) - return false; - - return true; -} - -static bool s_has_sse42(void) { - uint32_t abcd[4]; - uint32_t sse42_mask = 0x00100000; - aws_run_cpuid(1, 0, abcd); - - if ((abcd[2] & sse42_mask) != sse42_mask) - return false; - - return true; -} + aws_run_cpuid(0x0, 0x0, abcd); + const uint32_t max_cpuid_eax_value = abcd[0]; /* max-value = EAX */ + + /************************************************************************** + * CPUID(EAX=1H, ECX=0H): Processor Info and Feature Bits + * https://en.wikipedia.org/w/index.php?title=CPUID&oldid=1270569388#EAX=1:_Processor_Info_and_Feature_Bits + **************************************************************************/ + if (0x1 > max_cpuid_eax_value) { + return; + } + aws_run_cpuid(0x1, 0x0, abcd); + s_cpu_features[AWS_CPU_FEATURE_CLMUL] = abcd[2] & (1 << 1); /* pclmulqdq = ECX[bit 1] */ + s_cpu_features[AWS_CPU_FEATURE_SSE_4_1] = abcd[2] & (1 << 19); /* sse4.1 = ECX[bit 19] */ + s_cpu_features[AWS_CPU_FEATURE_SSE_4_2] = abcd[2] & (1 << 20); /* sse4.2 = ECX[bit 20] */ + + /* NOTE: Even if the AVX flag is set, it's not necessarily usable. + * We need to check that OSXSAVE is enabled, and check further capabilities via XGETBV. + * GCC had the same bug until 7.4: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85100 */ + bool avx_usable = false; + bool avx512_usable = false; + bool feature_osxsave = abcd[2] & (1 << 27); /* osxsave = ECX[bit 27] */ + if (feature_osxsave) { + /* Check XCR0 (Extended Control Register 0) via XGETBV + * https://en.wikipedia.org/w/index.php?title=Control_register&oldid=1268423710#XCR0_and_XSS */ + uint64_t xcr0 = aws_run_xgetbv(0); + const uint64_t avx_mask = (1 << 1) /* SSE = XCR0[bit 1] */ + | (1 << 2) /* AVX = XCR0[bit 2] */; + avx_usable = (xcr0 & avx_mask) == avx_mask; + + const uint64_t avx512_mask = (1 << 5) /* OPMASK = XCR0[bit 5] */ + | (1 << 6) /* ZMM_Hi256 = XCR0[bit 6] */ + | (1 << 7) /* Hi16_ZMM = XCR0[bit 7] */ + | avx_mask; + avx512_usable = (xcr0 & avx512_mask) == avx512_mask; + } -static bool s_has_avx2(void) { - uint32_t abcd[4]; + bool feature_avx = false; + if (avx_usable) { + feature_avx = abcd[2] & (1 << 28); /* avx = ECX[bit 28] */ + } - /* Check AVX2: - * CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]==1 */ - uint32_t avx2_mask = (1 << 5); - aws_run_cpuid(7, 0, abcd); - if ((abcd[1] & avx2_mask) != avx2_mask) { - return false; + /*************************************************************************** + * CPUID(EAX=7H, ECX=0H): Extended Features + * https://en.wikipedia.org/w/index.php?title=CPUID&oldid=1270569388#EAX=7,_ECX=0:_Extended_Features + **************************************************************************/ + if (0x7 > max_cpuid_eax_value) { + return; } + aws_run_cpuid(0x7, 0x0, abcd); + s_cpu_features[AWS_CPU_FEATURE_BMI2] = abcd[1] & (1 << 8); /* bmi2 = EBX[bit 8] */ - /* Also check AVX: - * CPUID.(EAX=01H, ECX=0H):ECX.AVX[bit 28]==1 - * - * NOTE: It SHOULD be impossible for a CPU to support AVX2 without supporting AVX. + /* NOTE: It SHOULD be impossible for a CPU to support AVX2 without supporting AVX. * But we've received crash reports where the AVX2 feature check passed * and then an AVX instruction caused an "invalid instruction" crash. * @@ -76,69 +88,26 @@ static bool s_has_avx2(void) { * * We don't know for sure what was up with those machines, but this extra * check should stop them from running our AVX/AVX2 code paths. */ - uint32_t avx1_mask = (1 << 28); - aws_run_cpuid(1, 0, abcd); - if ((abcd[2] & avx1_mask) != avx1_mask) { - return false; - } - - return true; -} - -static bool s_has_avx512(void) { - uint32_t abcd[4]; - - /* Check AVX512F: - * CPUID.(EAX=07H, ECX=0H):EBX.AVX512[bit 16]==1 */ - uint32_t avx512_mask = (1 << 16); - aws_run_cpuid(7, 0, abcd); - if ((abcd[1] & avx512_mask) != avx512_mask) { - return false; - } - - return true; -} - -static bool s_has_bmi2(void) { - uint32_t abcd[4]; - - /* Check BMI2: - * CPUID.(EAX=07H, ECX=0H):EBX.BMI2[bit 8]==1 */ - uint32_t bmi2_mask = (1 << 8); - aws_run_cpuid(7, 0, abcd); - if ((abcd[1] & bmi2_mask) != bmi2_mask) { - return false; + if (feature_avx) { + if (avx_usable) { + s_cpu_features[AWS_CPU_FEATURE_AVX2] = abcd[1] & (1 << 5); /* AVX2 = EBX[bit 5] */ + s_cpu_features[AWS_CPU_FEATURE_VPCLMULQDQ] = abcd[2] & (1 << 10); /* vpclmulqdq = ECX[bit 10] */ + } + if (avx512_usable) { + s_cpu_features[AWS_CPU_FEATURE_AVX512] = abcd[1] & (1 << 16); /* AVX-512 Foundation = EBX[bit 16] */ + } } - - return true; } -static bool s_has_vpclmulqdq(void) { - uint32_t abcd[4]; - /* Check VPCLMULQDQ: - * CPUID.(EAX=07H, ECX=0H):ECX.VPCLMULQDQ[bit 10]==1 */ - uint32_t vpclmulqdq_mask = (1 << 10); - aws_run_cpuid(7, 0, abcd); - if ((abcd[2] & vpclmulqdq_mask) != vpclmulqdq_mask) { - return false; +bool aws_cpu_has_feature(enum aws_cpu_feature_name feature_name) { + /* Look up and cache all hardware features the first time this is called */ + if (AWS_UNLIKELY(!s_cpu_features_cached)) { + s_cache_cpu_features(); + s_cpu_features_cached = true; } - return true; -} -has_feature_fn *s_check_cpu_feature[AWS_CPU_FEATURE_COUNT] = { - [AWS_CPU_FEATURE_CLMUL] = s_has_clmul, - [AWS_CPU_FEATURE_SSE_4_1] = s_has_sse41, - [AWS_CPU_FEATURE_SSE_4_2] = s_has_sse42, - [AWS_CPU_FEATURE_AVX2] = s_has_avx2, - [AWS_CPU_FEATURE_AVX512] = s_has_avx512, - [AWS_CPU_FEATURE_BMI2] = s_has_bmi2, - [AWS_CPU_FEATURE_VPCLMULQDQ] = s_has_vpclmulqdq, -}; - -bool aws_cpu_has_feature(enum aws_cpu_feature_name feature_name) { - if (s_check_cpu_feature[feature_name]) - return s_check_cpu_feature[feature_name](); - return false; + AWS_ASSERT(feature_name >= 0 && feature_name < AWS_CPU_FEATURE_COUNT); + return s_cpu_features[feature_name]; } #define CPUID_AVAILABLE 0 diff --git a/contrib/restricted/aws/aws-c-common/source/arch/intel/encoding_avx2.c b/contrib/restricted/aws/aws-c-common/source/arch/intel/encoding_avx2.c index 439d6ddada9..92c4abdfa76 100644 --- a/contrib/restricted/aws/aws-c-common/source/arch/intel/encoding_avx2.c +++ b/contrib/restricted/aws/aws-c-common/source/arch/intel/encoding_avx2.c @@ -194,13 +194,13 @@ static inline bool decode(const unsigned char *in, unsigned char *out) { size_t aws_common_private_base64_decode_sse41(const unsigned char *in, unsigned char *out, size_t len) { if (len % 4) { - return (size_t)-1; + return SIZE_MAX; } size_t outlen = 0; while (len > 32) { if (!decode(in, out)) { - return (size_t)-1; + return SIZE_MAX; } len -= 32; in += 32; @@ -230,13 +230,13 @@ size_t aws_common_private_base64_decode_sse41(const unsigned char *in, unsigned } if (!decode(tmp_in, tmp_out)) { - return (size_t)-1; + return SIZE_MAX; } /* Check that there are no trailing ones bits */ for (size_t i = final_out; i < sizeof(tmp_out); i++) { if (tmp_out[i]) { - return (size_t)-1; + return SIZE_MAX; } } diff --git a/contrib/restricted/aws/aws-c-common/source/array_list.c b/contrib/restricted/aws/aws-c-common/source/array_list.c index b6ea5a09013..a890115e913 100644 --- a/contrib/restricted/aws/aws-c-common/source/array_list.c +++ b/contrib/restricted/aws/aws-c-common/source/array_list.c @@ -184,9 +184,12 @@ static void aws_array_list_mem_swap(void *AWS_RESTRICT item1, void *AWS_RESTRICT } size_t remainder = item_size & (SLICE - 1); /* item_size % SLICE */ - memcpy((void *)temp, (void *)item1, remainder); - memcpy((void *)item1, (void *)item2, remainder); - memcpy((void *)item2, (void *)temp, remainder); + + if (remainder) { + memcpy((void *)temp, (void *)item1, remainder); + memcpy((void *)item1, (void *)item2, remainder); + memcpy((void *)item2, (void *)temp, remainder); + } } void aws_array_list_swap(struct aws_array_list *AWS_RESTRICT list, size_t a, size_t b) { diff --git a/contrib/restricted/aws/aws-c-common/source/byte_buf.c b/contrib/restricted/aws/aws-c-common/source/byte_buf.c index b815b6bfb74..da3748e812b 100644 --- a/contrib/restricted/aws/aws-c-common/source/byte_buf.c +++ b/contrib/restricted/aws/aws-c-common/source/byte_buf.c @@ -816,6 +816,25 @@ int aws_byte_buf_reserve_relative(struct aws_byte_buf *buffer, size_t additional return aws_byte_buf_reserve(buffer, requested_capacity); } +int aws_byte_buf_reserve_smart(struct aws_byte_buf *buffer, size_t requested_capacity) { + + if (requested_capacity <= buffer->capacity) { + AWS_POSTCONDITION(aws_byte_buf_is_valid(buffer)); + return AWS_OP_SUCCESS; + } + size_t double_current_capacity = aws_add_size_saturating(buffer->capacity, buffer->capacity); + size_t new_capacity = aws_max_size(requested_capacity, double_current_capacity); + return aws_byte_buf_reserve(buffer, new_capacity); +} + +int aws_byte_buf_reserve_smart_relative(struct aws_byte_buf *buffer, size_t additional_length) { + size_t requested_capacity = 0; + if (AWS_UNLIKELY(aws_add_size_checked(buffer->len, additional_length, &requested_capacity))) { + return AWS_OP_ERR; + } + return aws_byte_buf_reserve_smart(buffer, requested_capacity); +} + struct aws_byte_cursor aws_byte_cursor_right_trim_pred( const struct aws_byte_cursor *source, aws_byte_predicate_fn *predicate) { diff --git a/contrib/restricted/aws/aws-c-common/source/cbor.c b/contrib/restricted/aws/aws-c-common/source/cbor.c new file mode 100644 index 00000000000..b6ec4f239a6 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/cbor.c @@ -0,0 +1,647 @@ +#include "external/libcbor/cbor.h" +#include <aws/common/cbor.h> + +#include <aws/common/array_list.h> +#include <aws/common/logging.h> +#include <aws/common/private/byte_buf.h> +#include <aws/common/private/external_module_impl.h> +#include <float.h> +#include <inttypes.h> +#include <math.h> + +static bool s_aws_cbor_module_initialized = false; + +const static size_t s_cbor_element_width_64bit = 9; +const static size_t s_cbor_element_width_32bit = 5; + +enum s_cbor_simple_val { + AWS_CBOR_SIMPLE_VAL_FALSE = 20, + AWS_CBOR_SIMPLE_VAL_TRUE = 21, + AWS_CBOR_SIMPLE_VAL_NULL = 22, + AWS_CBOR_SIMPLE_VAL_UNDEFINED = 23, + AWS_CBOR_SIMPLE_VAL_BREAK = 31, +}; + +void aws_cbor_module_init(struct aws_allocator *allocator) { + (void)allocator; + if (!s_aws_cbor_module_initialized) { + /* Not allow any allocation from libcbor */ + cbor_set_allocs(NULL, NULL, NULL); + s_aws_cbor_module_initialized = true; + } +} + +void aws_cbor_module_cleanup(void) { + if (s_aws_cbor_module_initialized) { + s_aws_cbor_module_initialized = false; + } +} + +/* Return c-string for aws_cbor_type */ +const char *aws_cbor_type_cstr(enum aws_cbor_type type) { + /* clang-format off */ + switch (type) { + case (AWS_CBOR_TYPE_UINT): return "AWS_CBOR_TYPE_UINT"; + case (AWS_CBOR_TYPE_NEGINT): return "AWS_CBOR_TYPE_NEGINT"; + case (AWS_CBOR_TYPE_FLOAT): return "AWS_CBOR_TYPE_FLOAT"; + case (AWS_CBOR_TYPE_BYTES): return "AWS_CBOR_TYPE_BYTES"; + case (AWS_CBOR_TYPE_TEXT): return "AWS_CBOR_TYPE_TEXT"; + case (AWS_CBOR_TYPE_ARRAY_START): return "AWS_CBOR_TYPE_ARRAY_START"; + case (AWS_CBOR_TYPE_MAP_START): return "AWS_CBOR_TYPE_MAP_START"; + case (AWS_CBOR_TYPE_TAG): return "AWS_CBOR_TYPE_TAG"; + case (AWS_CBOR_TYPE_BOOL): return "AWS_CBOR_TYPE_BOOL"; + case (AWS_CBOR_TYPE_NULL): return "AWS_CBOR_TYPE_NULL"; + case (AWS_CBOR_TYPE_UNDEFINED): return "AWS_CBOR_TYPE_UNDEFINED"; + case (AWS_CBOR_TYPE_BREAK): return "AWS_CBOR_TYPE_BREAK"; + case (AWS_CBOR_TYPE_INDEF_BYTES_START): return "AWS_CBOR_TYPE_INDEF_BYTES_START"; + case (AWS_CBOR_TYPE_INDEF_TEXT_START): return "AWS_CBOR_TYPE_INDEF_TEXT_START"; + case (AWS_CBOR_TYPE_INDEF_ARRAY_START): return "AWS_CBOR_TYPE_INDEF_ARRAY_START"; + case (AWS_CBOR_TYPE_INDEF_MAP_START): return "AWS_CBOR_TYPE_INDEF_MAP_START"; + default: return "<UNKNOWN TYPE>"; + } + /* clang-format on */ +} + +/******************************************************************************* + * ENCODE + ******************************************************************************/ + +struct aws_cbor_encoder { + struct aws_allocator *allocator; + struct aws_byte_buf encoded_buf; +}; + +struct aws_cbor_encoder *aws_cbor_encoder_new(struct aws_allocator *allocator) { + struct aws_cbor_encoder *encoder = aws_mem_calloc(allocator, 1, sizeof(struct aws_cbor_encoder)); + encoder->allocator = allocator; + aws_byte_buf_init(&encoder->encoded_buf, allocator, 256); + + return encoder; +} + +struct aws_cbor_encoder *aws_cbor_encoder_destroy(struct aws_cbor_encoder *encoder) { + aws_byte_buf_clean_up(&encoder->encoded_buf); + aws_mem_release(encoder->allocator, encoder); + return NULL; +} + +struct aws_byte_cursor aws_cbor_encoder_get_encoded_data(const struct aws_cbor_encoder *encoder) { + return aws_byte_cursor_from_buf(&encoder->encoded_buf); +} + +void aws_cbor_encoder_reset(struct aws_cbor_encoder *encoder) { + aws_byte_buf_reset(&encoder->encoded_buf, false); +} + +static uint8_t *s_get_encoder_current_position(struct aws_cbor_encoder *encoder) { + return encoder->encoded_buf.buffer + encoder->encoded_buf.len; +} + +static size_t s_get_encoder_remaining_len(struct aws_cbor_encoder *encoder) { + return encoder->encoded_buf.capacity - encoder->encoded_buf.len; +} + +/** + * @brief Marcos to ensure the encoder have enough space to encode the value into the buffer using given `fn`, and then + * encode it. + */ +#define ENCODE_THROUGH_LIBCBOR(encoder, length_to_reserve, value, fn) \ + do { \ + int error = aws_byte_buf_reserve_smart_relative(&(encoder)->encoded_buf, length_to_reserve); \ + (void)error; \ + AWS_FATAL_ASSERT(error == AWS_ERROR_SUCCESS); \ + size_t encoded_len = fn(value, s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); \ + AWS_FATAL_ASSERT((encoded_len) != 0); \ + (encoder)->encoded_buf.len += (encoded_len); \ + } while (false) + +void aws_cbor_encoder_write_uint(struct aws_cbor_encoder *encoder, uint64_t value) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, value, cbor_encode_uint); +} + +void aws_cbor_encoder_write_negint(struct aws_cbor_encoder *encoder, uint64_t value) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, value, cbor_encode_negint); +} + +void aws_cbor_encoder_write_single_float(struct aws_cbor_encoder *encoder, float value) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_32bit, value, cbor_encode_single); +} + +void aws_cbor_encoder_write_float(struct aws_cbor_encoder *encoder, double value) { + /** + * As suggested by AWS SDK SEP, write the float value as small as possible. But, do not encode to half-float. + * Convert the float value to integer if the conversion will not cause any precision loss. + */ + if (!isfinite(value)) { + /* For special value: NAN/INFINITY, type cast to float and encode into single float. */ + aws_cbor_encoder_write_single_float(encoder, (float)value); + return; + } + /* Conversation from int to floating-type is implementation defined if loss of precision */ + if (value <= (double)INT64_MAX && value >= (double)INT64_MIN) { + /** + * A prvalue of a floating point type can be converted to a prvalue of an integer type. The conversion + * truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot + * be represented in the destination type. + * Check against the INT64 range to avoid undefined behavior + * + * Comparing against INT64_MAX instead of UINT64_MAX to simplify the code, which may loss the opportunity to + * convert the UINT64 range from double to uint64_t. However, converting double to uint64_t will not benefit the + * total length encoded. + **/ + int64_t int_value = (int64_t)value; + if (value == (double)int_value) { + if (int_value < 0) { + aws_cbor_encoder_write_negint(encoder, (uint64_t)(-1 - int_value)); + } else { + aws_cbor_encoder_write_uint(encoder, (uint64_t)(int_value)); + } + return; + } + } + if (value <= FLT_MAX && value >= -FLT_MAX) { + /* Only try to convert the value within the range of float. */ + float float_value = (float)value; + double converted_value = (double)float_value; + /* Try to cast a round trip to detect any precision loss. */ + if (value == converted_value) { + aws_cbor_encoder_write_single_float(encoder, float_value); + return; + } + } + + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, value, cbor_encode_double); +} + +void aws_cbor_encoder_write_map_start(struct aws_cbor_encoder *encoder, size_t number_entries) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, number_entries, cbor_encode_map_start); +} + +void aws_cbor_encoder_write_tag(struct aws_cbor_encoder *encoder, uint64_t tag_number) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, tag_number, cbor_encode_tag); +} + +void aws_cbor_encoder_write_array_start(struct aws_cbor_encoder *encoder, size_t number_entries) { + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit, number_entries, cbor_encode_array_start); +} + +void aws_cbor_encoder_write_bytes(struct aws_cbor_encoder *encoder, struct aws_byte_cursor from) { + /* Reserve the bytes for the byte string start cbor item and the actual bytes */ + /* Encode the first cbor item for byte string */ + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit + from.len, from.len, cbor_encode_bytestring_start); + /* Append the actual bytes to follow the cbor item */ + aws_byte_buf_append(&encoder->encoded_buf, &from); +} + +void aws_cbor_encoder_write_text(struct aws_cbor_encoder *encoder, struct aws_byte_cursor from) { + /* Reserve the bytes for the byte string start cbor item and the actual string */ + /* Encode the first cbor item for byte string */ + ENCODE_THROUGH_LIBCBOR(encoder, s_cbor_element_width_64bit + from.len, from.len, cbor_encode_string_start); + /* Append the actual string to follow the cbor item */ + aws_byte_buf_append(&encoder->encoded_buf, &from); +} + +void aws_cbor_encoder_write_bool(struct aws_cbor_encoder *encoder, bool value) { + /* Major type 7 (simple), value 20 (false) and 21 (true) */ + uint8_t ctrl_value = value == true ? AWS_CBOR_SIMPLE_VAL_TRUE : AWS_CBOR_SIMPLE_VAL_FALSE; + ENCODE_THROUGH_LIBCBOR(encoder, 1, ctrl_value, cbor_encode_ctrl); +} + +void aws_cbor_encoder_write_null(struct aws_cbor_encoder *encoder) { + /* Major type 7 (simple), value 22 (null) */ + ENCODE_THROUGH_LIBCBOR(encoder, 1, AWS_CBOR_SIMPLE_VAL_NULL /*null*/, cbor_encode_ctrl); +} + +void aws_cbor_encoder_write_undefined(struct aws_cbor_encoder *encoder) { + /* Major type 7 (simple), value 23 (undefined) */ + ENCODE_THROUGH_LIBCBOR(encoder, 1, AWS_CBOR_SIMPLE_VAL_UNDEFINED /*undefined*/, cbor_encode_ctrl); +} + +static void s_cbor_encoder_write_type_only(struct aws_cbor_encoder *encoder, enum aws_cbor_type type) { + /* All inf start takes 1 byte only */ + aws_byte_buf_reserve_smart_relative(&encoder->encoded_buf, 1); + size_t encoded_len = 0; + switch (type) { + case AWS_CBOR_TYPE_INDEF_BYTES_START: + encoded_len = cbor_encode_indef_bytestring_start( + s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); + break; + case AWS_CBOR_TYPE_INDEF_TEXT_START: + encoded_len = cbor_encode_indef_string_start( + s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); + break; + case AWS_CBOR_TYPE_INDEF_ARRAY_START: + encoded_len = cbor_encode_indef_array_start( + s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); + break; + case AWS_CBOR_TYPE_INDEF_MAP_START: + encoded_len = cbor_encode_indef_map_start( + s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); + break; + case AWS_CBOR_TYPE_BREAK: + encoded_len = + cbor_encode_break(s_get_encoder_current_position(encoder), s_get_encoder_remaining_len(encoder)); + break; + + default: + AWS_ASSERT(false); + break; + } + AWS_ASSERT(encoded_len == 1); + encoder->encoded_buf.len += encoded_len; +} +void aws_cbor_encoder_write_indef_bytes_start(struct aws_cbor_encoder *encoder) { + s_cbor_encoder_write_type_only(encoder, AWS_CBOR_TYPE_INDEF_BYTES_START); +} + +void aws_cbor_encoder_write_indef_text_start(struct aws_cbor_encoder *encoder) { + s_cbor_encoder_write_type_only(encoder, AWS_CBOR_TYPE_INDEF_TEXT_START); +} + +void aws_cbor_encoder_write_indef_array_start(struct aws_cbor_encoder *encoder) { + s_cbor_encoder_write_type_only(encoder, AWS_CBOR_TYPE_INDEF_ARRAY_START); +} + +void aws_cbor_encoder_write_indef_map_start(struct aws_cbor_encoder *encoder) { + s_cbor_encoder_write_type_only(encoder, AWS_CBOR_TYPE_INDEF_MAP_START); +} + +void aws_cbor_encoder_write_break(struct aws_cbor_encoder *encoder) { + s_cbor_encoder_write_type_only(encoder, AWS_CBOR_TYPE_BREAK); +} + +/******************************************************************************* + * DECODE + ******************************************************************************/ + +struct aws_cbor_decoder_context { + enum aws_cbor_type type; + + /* All the values only valid when the type is set to corresponding type. */ + union { + uint64_t unsigned_int_val; + uint64_t negative_int_val; + double float_val; + uint64_t tag_val; + bool boolean_val; + struct aws_byte_cursor bytes_val; + struct aws_byte_cursor text_val; + uint64_t map_start; + uint64_t array_start; + } u; +}; + +struct aws_cbor_decoder { + struct aws_allocator *allocator; + + struct aws_byte_cursor src; + + struct aws_cbor_decoder_context cached_context; + + /* Error code during decoding. Fail the decoding process without recovering, */ + int error_code; +}; + +struct aws_cbor_decoder *aws_cbor_decoder_new(struct aws_allocator *allocator, struct aws_byte_cursor src) { + + struct aws_cbor_decoder *decoder = aws_mem_calloc(allocator, 1, sizeof(struct aws_cbor_decoder)); + decoder->allocator = allocator; + decoder->src = src; + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + return decoder; +} + +struct aws_cbor_decoder *aws_cbor_decoder_destroy(struct aws_cbor_decoder *decoder) { + aws_mem_release(decoder->allocator, decoder); + return NULL; +} + +size_t aws_cbor_decoder_get_remaining_length(const struct aws_cbor_decoder *decoder) { + return decoder->src.len; +} + +#define LIBCBOR_VALUE_CALLBACK(field, callback_type, cbor_type) \ + static void s_##field##_callback(void *ctx, callback_type val) { \ + struct aws_cbor_decoder *decoder = ctx; \ + AWS_ASSERT((decoder)->cached_context.type == AWS_CBOR_TYPE_UNKNOWN); \ + (decoder)->cached_context.u.field = val; \ + (decoder)->cached_context.type = cbor_type; \ + } + +LIBCBOR_VALUE_CALLBACK(unsigned_int_val, uint64_t, AWS_CBOR_TYPE_UINT) +LIBCBOR_VALUE_CALLBACK(negative_int_val, uint64_t, AWS_CBOR_TYPE_NEGINT) +LIBCBOR_VALUE_CALLBACK(boolean_val, bool, AWS_CBOR_TYPE_BOOL) +LIBCBOR_VALUE_CALLBACK(float_val, double, AWS_CBOR_TYPE_FLOAT) +LIBCBOR_VALUE_CALLBACK(map_start, uint64_t, AWS_CBOR_TYPE_MAP_START) +LIBCBOR_VALUE_CALLBACK(array_start, uint64_t, AWS_CBOR_TYPE_ARRAY_START) +LIBCBOR_VALUE_CALLBACK(tag_val, uint64_t, AWS_CBOR_TYPE_TAG) + +static void s_uint8_callback(void *ctx, uint8_t data) { + s_unsigned_int_val_callback(ctx, (uint64_t)data); +} + +static void s_uint16_callback(void *ctx, uint16_t data) { + s_unsigned_int_val_callback(ctx, (uint64_t)data); +} + +static void s_uint32_callback(void *ctx, uint32_t data) { + s_unsigned_int_val_callback(ctx, (uint64_t)data); +} + +static void s_negint8_callback(void *ctx, uint8_t data) { + s_negative_int_val_callback(ctx, (uint64_t)data); +} + +static void s_negint16_callback(void *ctx, uint16_t data) { + s_negative_int_val_callback(ctx, (uint64_t)data); +} + +static void s_negint32_callback(void *ctx, uint32_t data) { + s_negative_int_val_callback(ctx, (uint64_t)data); +} + +static void s_float_callback(void *ctx, float data) { + s_float_val_callback(ctx, (double)data); +} + +static void s_bytes_callback(void *ctx, const unsigned char *cbor_data, uint64_t length) { + struct aws_cbor_decoder *decoder = ctx; + AWS_ASSERT((decoder)->cached_context.type == AWS_CBOR_TYPE_UNKNOWN); + if (length > SIZE_MAX) { + AWS_LOGF_ERROR(AWS_LS_COMMON_CBOR, "Decoded a bytes with %" PRIu64 " bytes causing overflow .", length); + decoder->error_code = AWS_ERROR_OVERFLOW_DETECTED; + return; + } + decoder->cached_context.type = AWS_CBOR_TYPE_BYTES; + decoder->cached_context.u.bytes_val.ptr = (uint8_t *)cbor_data; + decoder->cached_context.u.bytes_val.len = (size_t)length; +} + +static void s_str_callback(void *ctx, const unsigned char *cbor_data, uint64_t length) { + struct aws_cbor_decoder *decoder = ctx; + AWS_ASSERT((decoder)->cached_context.type == AWS_CBOR_TYPE_UNKNOWN); + if (length > SIZE_MAX) { + AWS_LOGF_ERROR(AWS_LS_COMMON_CBOR, "Decoded a string with %" PRIu64 " bytes causing overflow .", length); + decoder->error_code = AWS_ERROR_OVERFLOW_DETECTED; + return; + } + decoder->cached_context.type = AWS_CBOR_TYPE_TEXT; + decoder->cached_context.u.text_val.ptr = (uint8_t *)cbor_data; + decoder->cached_context.u.text_val.len = (size_t)length; +} + +#define LIBCBOR_SIMPLE_CALLBACK(field, cbor_type) \ + static void s_##field##_callback(void *ctx) { \ + struct aws_cbor_decoder *decoder = ctx; \ + AWS_ASSERT((decoder)->cached_context.type == AWS_CBOR_TYPE_UNKNOWN); \ + (decoder)->cached_context.type = cbor_type; \ + } + +LIBCBOR_SIMPLE_CALLBACK(inf_bytes, AWS_CBOR_TYPE_INDEF_BYTES_START) +LIBCBOR_SIMPLE_CALLBACK(inf_str, AWS_CBOR_TYPE_INDEF_TEXT_START) +LIBCBOR_SIMPLE_CALLBACK(inf_array, AWS_CBOR_TYPE_INDEF_ARRAY_START) +LIBCBOR_SIMPLE_CALLBACK(inf_map, AWS_CBOR_TYPE_INDEF_MAP_START) + +LIBCBOR_SIMPLE_CALLBACK(inf_break, AWS_CBOR_TYPE_BREAK) +LIBCBOR_SIMPLE_CALLBACK(undefined, AWS_CBOR_TYPE_UNDEFINED) +LIBCBOR_SIMPLE_CALLBACK(null, AWS_CBOR_TYPE_NULL) + +static struct cbor_callbacks s_callbacks = { + /** Unsigned int */ + .uint64 = s_unsigned_int_val_callback, + /** Unsigned int */ + .uint32 = s_uint32_callback, + /** Unsigned int */ + .uint16 = s_uint16_callback, + /** Unsigned int */ + .uint8 = s_uint8_callback, + + /** Negative int */ + .negint64 = s_negative_int_val_callback, + /** Negative int */ + .negint32 = s_negint32_callback, + /** Negative int */ + .negint16 = s_negint16_callback, + /** Negative int */ + .negint8 = s_negint8_callback, + + /** Indefinite byte string start */ + .byte_string_start = s_inf_bytes_callback, + /** Definite byte string */ + .byte_string = s_bytes_callback, + + /** Definite string */ + .string = s_str_callback, + /** Indefinite string start */ + .string_start = s_inf_str_callback, + + /** Definite array */ + .indef_array_start = s_inf_array_callback, + /** Indefinite array */ + .array_start = s_array_start_callback, + + /** Definite map */ + .indef_map_start = s_inf_map_callback, + /** Indefinite map */ + .map_start = s_map_start_callback, + + /** Tags */ + .tag = s_tag_val_callback, + + /** Half float */ + .float2 = s_float_callback, + /** Single float */ + .float4 = s_float_callback, + /** Double float */ + .float8 = s_float_val_callback, + /** Undef */ + .undefined = s_undefined_callback, + /** Null */ + .null = s_null_callback, + /** Bool */ + .boolean = s_boolean_val_callback, + + /** Indefinite item break */ + .indef_break = s_inf_break_callback, +}; + +/** + * decode the next element to the cached_content. + */ +static int s_cbor_decode_next_element(struct aws_cbor_decoder *decoder) { + struct cbor_decoder_result result = cbor_stream_decode(decoder->src.ptr, decoder->src.len, &s_callbacks, decoder); + switch (result.status) { + case CBOR_DECODER_NEDATA: + AWS_LOGF_ERROR( + AWS_LS_COMMON_CBOR, + "The decoder doesn't have enough data to decode the next element. At least %zu bytes more needed.", + result.required); + decoder->error_code = AWS_ERROR_INVALID_CBOR; + break; + case CBOR_DECODER_ERROR: + AWS_LOGF_ERROR(AWS_LS_COMMON_CBOR, "The cbor data is malformed to decode."); + decoder->error_code = AWS_ERROR_INVALID_CBOR; + break; + default: + break; + } + + if (decoder->error_code) { + /* Error happened during decoding */ + return aws_raise_error(decoder->error_code); + } + + aws_byte_cursor_advance(&decoder->src, result.read); + + return AWS_OP_SUCCESS; +} + +#define GET_NEXT_ITEM(field, out_type, expected_cbor_type) \ + /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \ + int aws_cbor_decoder_pop_next_##field(struct aws_cbor_decoder *decoder, out_type *out) { \ + if ((decoder)->error_code) { \ + /* Error happened during decoding */ \ + return aws_raise_error((decoder)->error_code); \ + } \ + if ((decoder)->cached_context.type != AWS_CBOR_TYPE_UNKNOWN) { \ + /* There was a cached context, check if the cached one meets the expected. */ \ + goto decode_done; \ + } \ + if (s_cbor_decode_next_element(decoder)) { \ + return AWS_OP_ERR; \ + } \ + decode_done: \ + if ((decoder)->cached_context.type != (expected_cbor_type)) { \ + AWS_LOGF_ERROR( \ + AWS_LS_COMMON_CBOR, \ + "The decoder got unexpected type: %d (%s), while expecting type: %d (%s).", \ + (decoder)->cached_context.type, \ + aws_cbor_type_cstr((decoder)->cached_context.type), \ + (expected_cbor_type), \ + aws_cbor_type_cstr(expected_cbor_type)); \ + return aws_raise_error(AWS_ERROR_CBOR_UNEXPECTED_TYPE); \ + } else { \ + /* Clear the cache as we give it out. */ \ + (decoder)->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; \ + *out = (decoder)->cached_context.u.field; \ + } \ + return AWS_OP_SUCCESS; \ + } + +GET_NEXT_ITEM(unsigned_int_val, uint64_t, AWS_CBOR_TYPE_UINT) +GET_NEXT_ITEM(negative_int_val, uint64_t, AWS_CBOR_TYPE_NEGINT) +GET_NEXT_ITEM(float_val, double, AWS_CBOR_TYPE_FLOAT) +GET_NEXT_ITEM(boolean_val, bool, AWS_CBOR_TYPE_BOOL) +GET_NEXT_ITEM(text_val, struct aws_byte_cursor, AWS_CBOR_TYPE_TEXT) +GET_NEXT_ITEM(bytes_val, struct aws_byte_cursor, AWS_CBOR_TYPE_BYTES) +GET_NEXT_ITEM(map_start, uint64_t, AWS_CBOR_TYPE_MAP_START) +GET_NEXT_ITEM(array_start, uint64_t, AWS_CBOR_TYPE_ARRAY_START) +GET_NEXT_ITEM(tag_val, uint64_t, AWS_CBOR_TYPE_TAG) + +int aws_cbor_decoder_peek_type(struct aws_cbor_decoder *decoder, enum aws_cbor_type *out_type) { + if (decoder->error_code) { + /* Error happened during decoding */ + return aws_raise_error(decoder->error_code); + } + + if (decoder->cached_context.type != AWS_CBOR_TYPE_UNKNOWN) { + /* There was a cached context, return the type. */ + *out_type = decoder->cached_context.type; + return AWS_OP_SUCCESS; + } + + /* Decode */ + if (s_cbor_decode_next_element(decoder)) { + return AWS_OP_ERR; + } + *out_type = decoder->cached_context.type; + return AWS_OP_SUCCESS; +} + +int aws_cbor_decoder_consume_next_whole_data_item(struct aws_cbor_decoder *decoder) { + if (decoder->error_code) { + /* Error happened during decoding */ + return aws_raise_error(decoder->error_code); + } + + if (decoder->cached_context.type == AWS_CBOR_TYPE_UNKNOWN) { + /* There was no cache, decode the next item */ + if (s_cbor_decode_next_element(decoder)) { + return AWS_OP_ERR; + } + } + switch (decoder->cached_context.type) { + case AWS_CBOR_TYPE_TAG: + /* Read the next data item */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + if (aws_cbor_decoder_consume_next_whole_data_item(decoder)) { + return AWS_OP_ERR; + } + break; + case AWS_CBOR_TYPE_MAP_START: { + uint64_t num_map_item = decoder->cached_context.u.map_start; + /* Reset type */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + for (uint64_t i = 0; i < num_map_item; i++) { + /* Key */ + if (aws_cbor_decoder_consume_next_whole_data_item(decoder)) { + return AWS_OP_ERR; + } + /* Value */ + if (aws_cbor_decoder_consume_next_whole_data_item(decoder)) { + return AWS_OP_ERR; + } + } + break; + } + case AWS_CBOR_TYPE_ARRAY_START: { + uint64_t num_array_item = decoder->cached_context.u.array_start; + /* Reset type */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + for (uint64_t i = 0; i < num_array_item; i++) { + /* item */ + if (aws_cbor_decoder_consume_next_whole_data_item(decoder)) { + return AWS_OP_ERR; + } + } + break; + } + case AWS_CBOR_TYPE_INDEF_BYTES_START: + case AWS_CBOR_TYPE_INDEF_TEXT_START: + case AWS_CBOR_TYPE_INDEF_ARRAY_START: + case AWS_CBOR_TYPE_INDEF_MAP_START: { + enum aws_cbor_type next_type; + /* Reset the cache for the tag val */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + if (aws_cbor_decoder_peek_type(decoder, &next_type)) { + return AWS_OP_ERR; + } + while (next_type != AWS_CBOR_TYPE_BREAK) { + if (aws_cbor_decoder_consume_next_whole_data_item(decoder)) { + return AWS_OP_ERR; + } + if (aws_cbor_decoder_peek_type(decoder, &next_type)) { + return AWS_OP_ERR; + } + } + break; + } + + default: + break; + } + + /* Done, just reset the cache */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + return AWS_OP_SUCCESS; +} + +int aws_cbor_decoder_consume_next_single_element(struct aws_cbor_decoder *decoder) { + enum aws_cbor_type out_type = 0; + if (aws_cbor_decoder_peek_type(decoder, &out_type)) { + return AWS_OP_ERR; + } + /* Reset the type to clear the cache. */ + decoder->cached_context.type = AWS_CBOR_TYPE_UNKNOWN; + return AWS_OP_SUCCESS; +} diff --git a/contrib/restricted/aws/aws-c-common/source/common.c b/contrib/restricted/aws/aws-c-common/source/common.c index 2c971b5b475..a391f4fcb1f 100644 --- a/contrib/restricted/aws/aws-c-common/source/common.c +++ b/contrib/restricted/aws/aws-c-common/source/common.c @@ -7,7 +7,7 @@ #include <aws/common/logging.h> #include <aws/common/math.h> #include <aws/common/private/dlloads.h> -#include <aws/common/private/json_impl.h> +#include <aws/common/private/external_module_impl.h> #include <aws/common/private/thread_shared.h> #include <stdarg.h> @@ -80,7 +80,7 @@ void aws_secure_zero(void *pBuf, size_t bufsize) { #endif // #else not windows } -#define AWS_DEFINE_ERROR_INFO_COMMON(C, ES) [(C)-0x0000] = AWS_DEFINE_ERROR_INFO(C, ES, "aws-c-common") +#define AWS_DEFINE_ERROR_INFO_COMMON(C, ES) [(C) - 0x0000] = AWS_DEFINE_ERROR_INFO(C, ES, "aws-c-common") /* clang-format off */ static struct aws_error_info errors[] = { AWS_DEFINE_ERROR_INFO_COMMON( @@ -274,6 +274,12 @@ static struct aws_error_info errors[] = { AWS_DEFINE_ERROR_INFO_COMMON( AWS_ERROR_FILE_WRITE_FAILURE, "Failed writing to file."), + AWS_DEFINE_ERROR_INFO_COMMON( + AWS_ERROR_INVALID_CBOR, + "Malformed cbor data."), + AWS_DEFINE_ERROR_INFO_COMMON( + AWS_ERROR_CBOR_UNEXPECTED_TYPE, + "Unexpected cbor type encountered."), }; /* clang-format on */ @@ -297,6 +303,8 @@ static struct aws_log_subject_info s_common_log_subject_infos[] = { DEFINE_LOG_SUBJECT_INFO(AWS_LS_COMMON_IO, "common-io", "Common IO utilities"), DEFINE_LOG_SUBJECT_INFO(AWS_LS_COMMON_BUS, "bus", "Message bus"), DEFINE_LOG_SUBJECT_INFO(AWS_LS_COMMON_TEST, "test", "Unit/integration testing"), + DEFINE_LOG_SUBJECT_INFO(AWS_LS_COMMON_JSON_PARSER, "json-parser", "Subject for json parser specific logging"), + DEFINE_LOG_SUBJECT_INFO(AWS_LS_COMMON_CBOR, "cbor", "Subject for CBOR encode and decode"), }; static struct aws_log_subject_info_list s_common_log_subject_list = { @@ -315,6 +323,7 @@ void aws_common_library_init(struct aws_allocator *allocator) { aws_register_log_subject_info_list(&s_common_log_subject_list); aws_thread_initialize_thread_management(); aws_json_module_init(allocator); + aws_cbor_module_init(allocator); /* NUMA is funky and we can't rely on libnuma.so being available. We also don't want to take a hard dependency on it, * try and load it if we can. */ @@ -349,26 +358,32 @@ void aws_common_library_init(struct aws_allocator *allocator) { } else { AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_available() failed to load"); } - - *(void **)(&g_numa_num_configured_nodes_ptr) = dlsym(g_libnuma_handle, "numa_num_configured_nodes"); - if (g_numa_num_configured_nodes_ptr) { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_configured_nodes() loaded"); + if (g_numa_available_ptr() == -1) { + AWS_LOGF_INFO( + AWS_LS_COMMON_GENERAL, + "static: numa_available() returns -1, numa functions are not available. Skip loading the other " + "numa functions."); } else { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_configured_nodes() failed to load"); - } + *(void **)(&g_numa_num_configured_nodes_ptr) = dlsym(g_libnuma_handle, "numa_num_configured_nodes"); + if (g_numa_num_configured_nodes_ptr) { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_configured_nodes() loaded"); + } else { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_configured_nodes() failed to load"); + } - *(void **)(&g_numa_num_possible_cpus_ptr) = dlsym(g_libnuma_handle, "numa_num_possible_cpus"); - if (g_numa_num_possible_cpus_ptr) { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_possible_cpus() loaded"); - } else { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_possible_cpus() failed to load"); - } + *(void **)(&g_numa_num_possible_cpus_ptr) = dlsym(g_libnuma_handle, "numa_num_possible_cpus"); + if (g_numa_num_possible_cpus_ptr) { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_possible_cpus() loaded"); + } else { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_num_possible_cpus() failed to load"); + } - *(void **)(&g_numa_node_of_cpu_ptr) = dlsym(g_libnuma_handle, "numa_node_of_cpu"); - if (g_numa_node_of_cpu_ptr) { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_node_of_cpu() loaded"); - } else { - AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_node_of_cpu() failed to load"); + *(void **)(&g_numa_node_of_cpu_ptr) = dlsym(g_libnuma_handle, "numa_node_of_cpu"); + if (g_numa_node_of_cpu_ptr) { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_node_of_cpu() loaded"); + } else { + AWS_LOGF_INFO(AWS_LS_COMMON_GENERAL, "static: numa_node_of_cpu() failed to load"); + } } } else { @@ -385,6 +400,7 @@ void aws_common_library_clean_up(void) { aws_unregister_error_info(&s_list); aws_unregister_log_subject_info_list(&s_common_log_subject_list); aws_json_module_cleanup(); + aws_cbor_module_cleanup(); #ifdef AWS_OS_LINUX if (g_libnuma_handle) { dlclose(g_libnuma_handle); 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); } diff --git a/contrib/restricted/aws/aws-c-common/source/external/cJSON.c b/contrib/restricted/aws/aws-c-common/source/external/cJSON.c index 9ca6351bf8c..8eac43afdf7 100644 --- a/contrib/restricted/aws/aws-c-common/source/external/cJSON.c +++ b/contrib/restricted/aws/aws-c-common/source/external/cJSON.c @@ -127,7 +127,7 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) } /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ -#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 17) +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18) #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #endif @@ -273,10 +273,12 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) { global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; } if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) { global_hooks.deallocate(item->string); + item->string = NULL; } global_hooks.deallocate(item); item = next; @@ -407,6 +409,7 @@ CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) return object->valuedouble = number; } +/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) { char *copy = NULL; @@ -415,8 +418,8 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) { return NULL; } - /* return NULL if the object is corrupted */ - if (object->valuestring == NULL) + /* return NULL if the object is corrupted or valuestring is NULL */ + if (object->valuestring == NULL || valuestring == NULL) { return NULL; } @@ -903,6 +906,7 @@ fail: if (output != NULL) { input_buffer->hooks.deallocate(output); + output = NULL; } if (input_pointer != NULL) @@ -1249,6 +1253,7 @@ static unsigned char *print(const cJSON * const item, cJSON_bool format, const i /* free the buffer */ hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; } return printed; @@ -1257,11 +1262,13 @@ fail: if (buffer->buffer != NULL) { hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; } if (printed != NULL) { hooks->deallocate(printed); + printed = NULL; } return NULL; @@ -1302,6 +1309,7 @@ CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON if (!print_value(item, &p)) { global_hooks.deallocate(p.buffer); + p.buffer = NULL; return NULL; } @@ -1673,6 +1681,11 @@ static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_bu current_item = new_item; } + if (cannot_access_at_index(input_buffer, 1)) + { + goto fail; /* nothing comes after the comma */ + } + /* parse the name of the child */ input_buffer->offset++; buffer_skip_whitespace(input_buffer); @@ -3140,6 +3153,7 @@ CJSON_PUBLIC(void *) cJSON_malloc(size_t size) CJSON_PUBLIC(void) cJSON_free(void *object) { global_hooks.deallocate(object); + object = NULL; } /* Amazon edit */ /* NOLINTEND */ diff --git a/contrib/restricted/aws/aws-c-common/source/external/cJSON.h b/contrib/restricted/aws/aws-c-common/source/external/cJSON.h index 47594475ee0..48cdda9acb0 100644 --- a/contrib/restricted/aws/aws-c-common/source/external/cJSON.h +++ b/contrib/restricted/aws/aws-c-common/source/external/cJSON.h @@ -88,7 +88,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ /* project version */ #define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MINOR 7 -#define CJSON_VERSION_PATCH 17 +#define CJSON_VERSION_PATCH 18 #include <stddef.h> diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/allocators.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/allocators.c new file mode 100644 index 00000000000..43c5440ddb2 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/allocators.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "cbor/common.h" + +CBOR_EXPORT _cbor_malloc_t _cbor_malloc = malloc; +CBOR_EXPORT _cbor_realloc_t _cbor_realloc = realloc; +CBOR_EXPORT _cbor_free_t _cbor_free = free; + +void cbor_set_allocs(_cbor_malloc_t custom_malloc, + _cbor_realloc_t custom_realloc, _cbor_free_t custom_free) { + _cbor_malloc = custom_malloc; + _cbor_realloc = custom_realloc; + _cbor_free = custom_free; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.c new file mode 100644 index 00000000000..a8b4bcd7a08 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "cbor.h" +#include "cbor/internal/builder_callbacks.h" +#include "cbor/internal/loaders.h" + +#pragma clang diagnostic push +cbor_item_t *cbor_load(cbor_data source, size_t source_size, + struct cbor_load_result *result) { + /* Context stack */ + static struct cbor_callbacks callbacks = { + .uint8 = &cbor_builder_uint8_callback, + .uint16 = &cbor_builder_uint16_callback, + .uint32 = &cbor_builder_uint32_callback, + .uint64 = &cbor_builder_uint64_callback, + + .negint8 = &cbor_builder_negint8_callback, + .negint16 = &cbor_builder_negint16_callback, + .negint32 = &cbor_builder_negint32_callback, + .negint64 = &cbor_builder_negint64_callback, + + .byte_string = &cbor_builder_byte_string_callback, + .byte_string_start = &cbor_builder_byte_string_start_callback, + + .string = &cbor_builder_string_callback, + .string_start = &cbor_builder_string_start_callback, + + .array_start = &cbor_builder_array_start_callback, + .indef_array_start = &cbor_builder_indef_array_start_callback, + + .map_start = &cbor_builder_map_start_callback, + .indef_map_start = &cbor_builder_indef_map_start_callback, + + .tag = &cbor_builder_tag_callback, + + .null = &cbor_builder_null_callback, + .undefined = &cbor_builder_undefined_callback, + .boolean = &cbor_builder_boolean_callback, + .float2 = &cbor_builder_float2_callback, + .float4 = &cbor_builder_float4_callback, + .float8 = &cbor_builder_float8_callback, + .indef_break = &cbor_builder_indef_break_callback}; + + if (source_size == 0) { + result->error.code = CBOR_ERR_NODATA; + return NULL; + } + struct _cbor_stack stack = _cbor_stack_init(); + + /* Target for callbacks */ + struct _cbor_decoder_context context = (struct _cbor_decoder_context){ + .stack = &stack, .creation_failed = false, .syntax_error = false}; + struct cbor_decoder_result decode_result; + *result = + (struct cbor_load_result){.read = 0, .error = {.code = CBOR_ERR_NONE}}; + + do { + if (source_size > result->read) { /* Check for overflows */ + decode_result = + cbor_stream_decode(source + result->read, source_size - result->read, + &callbacks, &context); + } else { + result->error = (struct cbor_error){.code = CBOR_ERR_NOTENOUGHDATA, + .position = result->read}; + goto error; + } + + switch (decode_result.status) { + case CBOR_DECODER_FINISHED: + /* Everything OK */ + { + result->read += decode_result.read; + break; + } + case CBOR_DECODER_NEDATA: + /* Data length doesn't match MTB expectation */ + { + result->error.code = CBOR_ERR_NOTENOUGHDATA; + goto error; + } + case CBOR_DECODER_ERROR: + /* Reserved/malformed item */ + { + result->error.code = CBOR_ERR_MALFORMATED; + goto error; + } + } + + if (context.creation_failed) { + /* Most likely unsuccessful allocation - our callback has failed */ + result->error.code = CBOR_ERR_MEMERROR; + goto error; + } else if (context.syntax_error) { + result->error.code = CBOR_ERR_SYNTAXERROR; + goto error; + } + } while (stack.size > 0); + + return context.root; + +error: + result->error.position = result->read; + // debug_print("Failed with decoder error %d at %d\n", result->error.code, + // result->error.position); cbor_describe(stack.top->item, stdout); + /* Free the stack */ + while (stack.size > 0) { + cbor_decref(&stack.top->item); + _cbor_stack_pop(&stack); + } + return NULL; +} + +static cbor_item_t *_cbor_copy_int(cbor_item_t *item, bool negative) { + cbor_item_t *res; + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + res = cbor_build_uint8(cbor_get_uint8(item)); + break; + case CBOR_INT_16: + res = cbor_build_uint16(cbor_get_uint16(item)); + break; + case CBOR_INT_32: + res = cbor_build_uint32(cbor_get_uint32(item)); + break; + case CBOR_INT_64: + res = cbor_build_uint64(cbor_get_uint64(item)); + break; + } + + if (negative) cbor_mark_negint(res); + + return res; +} + +static cbor_item_t *_cbor_copy_float_ctrl(cbor_item_t *item) { + // cppcheck-suppress missingReturn + switch (cbor_float_get_width(item)) { + case CBOR_FLOAT_0: + return cbor_build_ctrl(cbor_ctrl_value(item)); + case CBOR_FLOAT_16: + return cbor_build_float2(cbor_float_get_float2(item)); + case CBOR_FLOAT_32: + return cbor_build_float4(cbor_float_get_float4(item)); + case CBOR_FLOAT_64: + return cbor_build_float8(cbor_float_get_float8(item)); + } +} + +cbor_item_t *cbor_copy(cbor_item_t *item) { + // cppcheck-suppress missingReturn + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: + return _cbor_copy_int(item, false); + case CBOR_TYPE_NEGINT: + return _cbor_copy_int(item, true); + case CBOR_TYPE_BYTESTRING: + if (cbor_bytestring_is_definite(item)) { + return cbor_build_bytestring(cbor_bytestring_handle(item), + cbor_bytestring_length(item)); + } else { + cbor_item_t *res = cbor_new_indefinite_bytestring(); + if (res == NULL) { + return NULL; + } + + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { + cbor_item_t *chunk_copy = + cbor_copy(cbor_bytestring_chunks_handle(item)[i]); + if (chunk_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_bytestring_add_chunk(res, chunk_copy)) { + cbor_decref(&chunk_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&chunk_copy); + } + return res; + } + case CBOR_TYPE_STRING: + if (cbor_string_is_definite(item)) { + return cbor_build_stringn((const char *)cbor_string_handle(item), + cbor_string_length(item)); + } else { + cbor_item_t *res = cbor_new_indefinite_string(); + if (res == NULL) { + return NULL; + } + + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { + cbor_item_t *chunk_copy = + cbor_copy(cbor_string_chunks_handle(item)[i]); + if (chunk_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_string_add_chunk(res, chunk_copy)) { + cbor_decref(&chunk_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&chunk_copy); + } + return res; + } + case CBOR_TYPE_ARRAY: { + cbor_item_t *res; + if (cbor_array_is_definite(item)) { + res = cbor_new_definite_array(cbor_array_size(item)); + } else { + res = cbor_new_indefinite_array(); + } + if (res == NULL) { + return NULL; + } + + for (size_t i = 0; i < cbor_array_size(item); i++) { + cbor_item_t *entry_copy = cbor_copy(cbor_move(cbor_array_get(item, i))); + if (entry_copy == NULL) { + cbor_decref(&res); + return NULL; + } + if (!cbor_array_push(res, entry_copy)) { + cbor_decref(&entry_copy); + cbor_decref(&res); + return NULL; + } + cbor_decref(&entry_copy); + } + return res; + } + case CBOR_TYPE_MAP: { + cbor_item_t *res; + if (cbor_map_is_definite(item)) { + res = cbor_new_definite_map(cbor_map_size(item)); + } else { + res = cbor_new_indefinite_map(); + } + if (res == NULL) { + return NULL; + } + + struct cbor_pair *it = cbor_map_handle(item); + for (size_t i = 0; i < cbor_map_size(item); i++) { + cbor_item_t *key_copy = cbor_copy(it[i].key); + if (key_copy == NULL) { + cbor_decref(&res); + return NULL; + } + cbor_item_t *value_copy = cbor_copy(it[i].value); + if (value_copy == NULL) { + cbor_decref(&res); + cbor_decref(&key_copy); + return NULL; + } + if (!cbor_map_add(res, (struct cbor_pair){.key = key_copy, + .value = value_copy})) { + cbor_decref(&res); + cbor_decref(&key_copy); + cbor_decref(&value_copy); + return NULL; + } + cbor_decref(&key_copy); + cbor_decref(&value_copy); + } + return res; + } + case CBOR_TYPE_TAG: { + cbor_item_t *item_copy = cbor_copy(cbor_move(cbor_tag_item(item))); + if (item_copy == NULL) { + return NULL; + } + cbor_item_t *tag = cbor_build_tag(cbor_tag_value(item), item_copy); + cbor_decref(&item_copy); + return tag; + } + case CBOR_TYPE_FLOAT_CTRL: + return _cbor_copy_float_ctrl(item); + } +} + +#if CBOR_PRETTY_PRINTER + +#include <inttypes.h> +#include <locale.h> +#include <wchar.h> + +#define __STDC_FORMAT_MACROS + +static int _pow(int b, int ex) { + if (ex == 0) return 1; + int res = b; + while (--ex > 0) res *= b; + return res; +} + +static void _cbor_type_marquee(FILE *out, char *label, int indent) { + fprintf(out, "%*.*s[%s] ", indent, indent, " ", label); +} + +static void _cbor_nested_describe(cbor_item_t *item, FILE *out, int indent) { + const int indent_offset = 4; + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: { + _cbor_type_marquee(out, "CBOR_TYPE_UINT", indent); + fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); + fprintf(out, "Value: %" PRIu64 "\n", cbor_get_int(item)); + break; + } + case CBOR_TYPE_NEGINT: { + _cbor_type_marquee(out, "CBOR_TYPE_NEGINT", indent); + fprintf(out, "Width: %dB, ", _pow(2, cbor_int_get_width(item))); + fprintf(out, "Value: -%" PRIu64 " - 1\n", cbor_get_int(item)); + break; + } + case CBOR_TYPE_BYTESTRING: { + _cbor_type_marquee(out, "CBOR_TYPE_BYTESTRING", indent); + if (cbor_bytestring_is_indefinite(item)) { + fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n", + cbor_bytestring_chunk_count(item)); + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) + _cbor_nested_describe(cbor_bytestring_chunks_handle(item)[i], out, + indent + indent_offset); + } else { + const unsigned char *data = cbor_bytestring_handle(item); + fprintf(out, "Definite, Length: %zuB, Data:\n", + cbor_bytestring_length(item)); + fprintf(out, "%*s", indent + indent_offset, " "); + for (size_t i = 0; i < cbor_bytestring_length(item); i++) + fprintf(out, "%02x", (int)(data[i] & 0xff)); + fprintf(out, "\n"); + } + break; + } + case CBOR_TYPE_STRING: { + _cbor_type_marquee(out, "CBOR_TYPE_STRING", indent); + if (cbor_string_is_indefinite(item)) { + fprintf(out, "Indefinite, Chunks: %zu, Chunk data:\n", + cbor_string_chunk_count(item)); + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) + _cbor_nested_describe(cbor_string_chunks_handle(item)[i], out, + indent + indent_offset); + } else { + fprintf(out, "Definite, Length: %zuB, Codepoints: %zu, Data:\n", + cbor_string_length(item), cbor_string_codepoint_count(item)); + fprintf(out, "%*s", indent + indent_offset, " "); + // Note: The string is not escaped, whitespace and control character + // will be printed in verbatim and take effect. + fwrite(cbor_string_handle(item), sizeof(unsigned char), + cbor_string_length(item), out); + fprintf(out, "\n"); + } + break; + } + case CBOR_TYPE_ARRAY: { + _cbor_type_marquee(out, "CBOR_TYPE_ARRAY", indent); + if (cbor_array_is_definite(item)) { + fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_array_size(item)); + } else { + fprintf(out, "Indefinite, Size: %zu, Contents:\n", + cbor_array_size(item)); + } + + for (size_t i = 0; i < cbor_array_size(item); i++) + _cbor_nested_describe(cbor_array_handle(item)[i], out, + indent + indent_offset); + break; + } + case CBOR_TYPE_MAP: { + _cbor_type_marquee(out, "CBOR_TYPE_MAP", indent); + if (cbor_map_is_definite(item)) { + fprintf(out, "Definite, Size: %zu, Contents:\n", cbor_map_size(item)); + } else { + fprintf(out, "Indefinite, Size: %zu, Contents:\n", cbor_map_size(item)); + } + + // TODO: Label and group keys and values + for (size_t i = 0; i < cbor_map_size(item); i++) { + fprintf(out, "%*sMap entry %zu\n", indent + indent_offset, " ", i); + _cbor_nested_describe(cbor_map_handle(item)[i].key, out, + indent + 2 * indent_offset); + _cbor_nested_describe(cbor_map_handle(item)[i].value, out, + indent + 2 * indent_offset); + } + break; + } + case CBOR_TYPE_TAG: { + _cbor_type_marquee(out, "CBOR_TYPE_TAG", indent); + fprintf(out, "Value: %" PRIu64 "\n", cbor_tag_value(item)); + _cbor_nested_describe(cbor_move(cbor_tag_item(item)), out, + indent + indent_offset); + break; + } + case CBOR_TYPE_FLOAT_CTRL: { + _cbor_type_marquee(out, "CBOR_TYPE_FLOAT_CTRL", indent); + if (cbor_float_ctrl_is_ctrl(item)) { + if (cbor_is_bool(item)) + fprintf(out, "Bool: %s\n", cbor_get_bool(item) ? "true" : "false"); + else if (cbor_is_undef(item)) + fprintf(out, "Undefined\n"); + else if (cbor_is_null(item)) + fprintf(out, "Null\n"); + else + fprintf(out, "Simple value: %d\n", cbor_ctrl_value(item)); + } else { + fprintf(out, "Width: %dB, ", _pow(2, cbor_float_get_width(item))); + fprintf(out, "Value: %lf\n", cbor_float_get_float(item)); + } + break; + } + } +} + +void cbor_describe(cbor_item_t *item, FILE *out) { + _cbor_nested_describe(item, out, 0); +} + +#endif diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.h new file mode 100644 index 00000000000..46ef8f267ac --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_H_ +#define LIBCBOR_H_ + +#include "cbor/common.h" +#include "cbor/data.h" + +#include "cbor/arrays.h" +#include "cbor/bytestrings.h" +#include "cbor/floats_ctrls.h" +#include "cbor/ints.h" +#include "cbor/maps.h" +#include "cbor/strings.h" +#include "cbor/tags.h" + +#include "cbor/callbacks.h" +#include "cbor/cbor_export.h" +#include "cbor/encoding.h" +#include "cbor/serialization.h" +#include "cbor/streaming.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * High level decoding + * ============================================================================ + */ + +/** Loads data item from a buffer + * + * @param source The buffer + * @param source_size + * @param[out] result Result indicator. #CBOR_ERR_NONE on success + * @return Decoded CBOR item. The item's reference count is initialized to one. + * @return `NULL` on failure. In that case, \p result contains the location and + * description of the error. + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_load( + cbor_data source, size_t source_size, struct cbor_load_result* result); + +/** Take a deep copy of an item + * + * All items this item points to (array and map members, string chunks, tagged + * items) will be copied recursively using #cbor_copy. The new item doesn't + * alias or point to any items from the original \p item. All the reference + * counts in the new structure are set to one. + * + * @param item item to copy + * @return Reference to the new item. The item's reference count is initialized + * to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t* cbor_copy(cbor_item_t* item); + +#if CBOR_PRETTY_PRINTER +#include <stdio.h> + +CBOR_EXPORT void cbor_describe(cbor_item_t* item, FILE* out); +#endif + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_H_ diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.c new file mode 100644 index 00000000000..a23bbe3cd15 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "arrays.h" +#include <string.h> +#include "internal/memory_utils.h" + +size_t cbor_array_size(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_array(item)); + return item->metadata.array_metadata.end_ptr; +} + +size_t cbor_array_allocated(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_array(item)); + return item->metadata.array_metadata.allocated; +} + +cbor_item_t *cbor_array_get(const cbor_item_t *item, size_t index) { + return cbor_incref(((cbor_item_t **)item->data)[index]); +} + +bool cbor_array_set(cbor_item_t *item, size_t index, cbor_item_t *value) { + if (index == item->metadata.array_metadata.end_ptr) { + return cbor_array_push(item, value); + } else if (index < item->metadata.array_metadata.end_ptr) { + return cbor_array_replace(item, index, value); + } else { + return false; + } +} + +bool cbor_array_replace(cbor_item_t *item, size_t index, cbor_item_t *value) { + if (index >= item->metadata.array_metadata.end_ptr) return false; + /* We cannot use cbor_array_get as that would increase the refcount */ + cbor_intermediate_decref(((cbor_item_t **)item->data)[index]); + ((cbor_item_t **)item->data)[index] = cbor_incref(value); + return true; +} + +bool cbor_array_push(cbor_item_t *array, cbor_item_t *pushee) { + CBOR_ASSERT(cbor_isa_array(array)); + struct _cbor_array_metadata *metadata = + (struct _cbor_array_metadata *)&array->metadata; + cbor_item_t **data = (cbor_item_t **)array->data; + if (cbor_array_is_definite(array)) { + /* Do not reallocate definite arrays */ + if (metadata->end_ptr >= metadata->allocated) { + return false; + } + data[metadata->end_ptr++] = pushee; + } else { + /* Exponential realloc */ + if (metadata->end_ptr >= metadata->allocated) { + // Check for overflows first + if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { + return false; + } + + size_t new_allocation = metadata->allocated == 0 + ? 1 + : CBOR_BUFFER_GROWTH * metadata->allocated; + + unsigned char *new_data = _cbor_realloc_multiple( + array->data, sizeof(cbor_item_t *), new_allocation); + if (new_data == NULL) { + return false; + } + + array->data = new_data; + metadata->allocated = new_allocation; + } + ((cbor_item_t **)array->data)[metadata->end_ptr++] = pushee; + } + cbor_incref(pushee); + return true; +} + +bool cbor_array_is_definite(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_array(item)); + return item->metadata.array_metadata.type == _CBOR_METADATA_DEFINITE; +} + +bool cbor_array_is_indefinite(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_array(item)); + return item->metadata.array_metadata.type == _CBOR_METADATA_INDEFINITE; +} + +cbor_item_t **cbor_array_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_array(item)); + return (cbor_item_t **)item->data; +} + +cbor_item_t *cbor_new_definite_array(size_t size) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + cbor_item_t **data = _cbor_alloc_multiple(sizeof(cbor_item_t *), size); + _CBOR_DEPENDENT_NOTNULL(item, data); + + for (size_t i = 0; i < size; i++) { + data[i] = NULL; + } + + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_ARRAY, + .metadata = {.array_metadata = {.type = _CBOR_METADATA_DEFINITE, + .allocated = size, + .end_ptr = 0}}, + .data = (unsigned char *)data}; + + return item; +} + +cbor_item_t *cbor_new_indefinite_array(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_ARRAY, + .metadata = {.array_metadata = {.type = _CBOR_METADATA_INDEFINITE, + .allocated = 0, + .end_ptr = 0}}, + .data = NULL /* Can be safely realloc-ed */ + }; + return item; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.h new file mode 100644 index 00000000000..db19e59d062 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/arrays.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_ARRAYS_H +#define LIBCBOR_ARRAYS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Get the number of members + * + * @param item An array + * @return The number of members + */ +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_array_size(const cbor_item_t* item); + +/** Get the size of the allocated storage + * + * @param item An array + * @return The size of the allocated storage (number of items) + */ +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_array_allocated(const cbor_item_t* item); + +/** Get item by index + * + * @param item An array + * @param index The index (zero-based) + * @return Reference to the item, or `NULL` in case of boundary violation. + * + * Increases the reference count of the underlying item. The returned reference + * must be released using #cbor_decref. + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_array_get(const cbor_item_t* item, size_t index); + +/** Set item by index + * + * If the index is out of bounds, the array is not modified and false is + * returned. Creating arrays with holes is not possible. + * + * @param item An array + * @param value The item to assign + * @param index The index (zero-based) + * @return `true` on success, `false` on allocation failure. + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_set(cbor_item_t* item, size_t index, + cbor_item_t* value); + +/** Replace item at an index + * + * The reference to the item being replaced will be released using #cbor_decref. + * + * @param item An array + * @param value The item to assign. Its reference count will be increased by + * one. + * @param index The index (zero-based) + * @return true on success, false on allocation failure. + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_replace(cbor_item_t* item, size_t index, + cbor_item_t* value); + +/** Is the array definite? + * + * @param item An array + * @return Is the array definite? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_is_definite(const cbor_item_t* item); + +/** Is the array indefinite? + * + * @param item An array + * @return Is the array indefinite? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_is_indefinite(const cbor_item_t* item); + +/** Get the array contents + * + * The items may be reordered and modified as long as references remain + * consistent. + * + * @param item An array item + * @return An array of #cbor_item_t pointers of size #cbor_array_size. + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t** cbor_array_handle(const cbor_item_t* item); + +/** Create new definite array + * + * @param size Number of slots to preallocate + * @return Reference to the new array item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_new_definite_array(size_t size); + +/** Create new indefinite array + * + * @return Reference to the new array item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t* cbor_new_indefinite_array(void); + +/** Append to the end + * + * For indefinite items, storage may be reallocated. For definite items, only + * the preallocated capacity is available. + * + * @param array An array + * @param pushee The item to push. Its reference count will be increased by + * one. + * @return `true` on success, `false` on failure + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_array_push(cbor_item_t* array, cbor_item_t* pushee); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_ARRAYS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.c new file mode 100644 index 00000000000..528937179ae --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "bytestrings.h" +#include <string.h> +#include "internal/memory_utils.h" + +size_t cbor_bytestring_length(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + return item->metadata.bytestring_metadata.length; +} + +unsigned char *cbor_bytestring_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + return item->data; +} + +bool cbor_bytestring_is_definite(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + return item->metadata.bytestring_metadata.type == _CBOR_METADATA_DEFINITE; +} + +bool cbor_bytestring_is_indefinite(const cbor_item_t *item) { + return !cbor_bytestring_is_definite(item); +} + +cbor_item_t *cbor_new_definite_bytestring(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_BYTESTRING, + .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_DEFINITE, + .length = 0}}}; + return item; +} + +cbor_item_t *cbor_new_indefinite_bytestring(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_BYTESTRING, + .metadata = {.bytestring_metadata = {.type = _CBOR_METADATA_INDEFINITE, + .length = 0}}, + .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))}; + _CBOR_DEPENDENT_NOTNULL(item, item->data); + *((struct cbor_indefinite_string_data *)item->data) = + (struct cbor_indefinite_string_data){ + .chunk_count = 0, + .chunk_capacity = 0, + .chunks = NULL, + }; + return item; +} + +cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length) { + cbor_item_t *item = cbor_new_definite_bytestring(); + _CBOR_NOTNULL(item); + void *content = _cbor_malloc(length); + _CBOR_DEPENDENT_NOTNULL(item, content); + memcpy(content, handle, length); + cbor_bytestring_set_handle(item, content, length); + return item; +} + +void cbor_bytestring_set_handle(cbor_item_t *item, + cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_definite(item)); + item->data = data; + item->metadata.bytestring_metadata.length = length; +} + +cbor_item_t **cbor_bytestring_chunks_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); + return ((struct cbor_indefinite_string_data *)item->data)->chunks; +} + +size_t cbor_bytestring_chunk_count(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); + return ((struct cbor_indefinite_string_data *)item->data)->chunk_count; +} + +bool cbor_bytestring_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); + CBOR_ASSERT(cbor_isa_bytestring(chunk)); + CBOR_ASSERT(cbor_bytestring_is_definite(chunk)); + struct cbor_indefinite_string_data *data = + (struct cbor_indefinite_string_data *)item->data; + if (data->chunk_count == data->chunk_capacity) { + if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { + return false; + } + + size_t new_chunk_capacity = + data->chunk_capacity == 0 ? 1 + : CBOR_BUFFER_GROWTH * (data->chunk_capacity); + + cbor_item_t **new_chunks_data = _cbor_realloc_multiple( + data->chunks, sizeof(cbor_item_t *), new_chunk_capacity); + + if (new_chunks_data == NULL) { + return false; + } + data->chunk_capacity = new_chunk_capacity; + data->chunks = new_chunks_data; + } + data->chunks[data->chunk_count++] = cbor_incref(chunk); + return true; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.h new file mode 100644 index 00000000000..cacd1adf95f --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/bytestrings.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_BYTESTRINGS_H +#define LIBCBOR_BYTESTRINGS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * Byte string manipulation + * ============================================================================ + */ + +/** Returns the length of the binary data + * + * For definite byte strings only + * + * @param item a definite bytestring + * @return length of the binary data. Zero if no chunk has been attached yet + */ +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_bytestring_length(const cbor_item_t *item); + +/** Is the byte string definite? + * + * @param item a byte string + * @return Is the byte string definite? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_is_definite(const cbor_item_t *item); + +/** Is the byte string indefinite? + * + * @param item a byte string + * @return Is the byte string indefinite? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_is_indefinite(const cbor_item_t *item); + +/** Get the handle to the binary data + * + * Definite items only. Modifying the data is allowed. In that case, the caller + * takes responsibility for the effect on items this item might be a part of + * + * @param item A definite byte string + * @return The address of the underlying binary data + * @return `NULL` if no data have been assigned + * yet. + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_mutable_data cbor_bytestring_handle(const cbor_item_t *item); + +/** Set the handle to the binary data + * + * @param item A definite byte string + * @param data The memory block. The caller gives up the ownership of the block. + * libcbor will deallocate it when appropriate using the `free` implementation + * configured using #cbor_set_allocs + * @param length Length of the data block + */ +CBOR_EXPORT void cbor_bytestring_set_handle( + cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length); + +/** Get the handle to the array of chunks + * + * Manipulations with the memory block (e.g. sorting it) are allowed, but the + * validity and the number of chunks must be retained. + * + * @param item A indefinite byte string + * @return array of #cbor_bytestring_chunk_count definite bytestrings + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t **cbor_bytestring_chunks_handle( + const cbor_item_t *item); + +/** Get the number of chunks this string consist of + * + * @param item A indefinite bytestring + * @return The chunk count. 0 for freshly created items. + */ +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_bytestring_chunk_count(const cbor_item_t *item); + +/** Appends a chunk to the bytestring + * + * Indefinite byte strings only. + * + * May realloc the chunk storage. + * + * @param item An indefinite byte string + * @param chunk A definite byte string. Its reference count will be be increased + * by one. + * @return true on success, false on realloc failure. In that case, the refcount + * of `chunk` is not increased and the `item` is left intact. + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_bytestring_add_chunk(cbor_item_t *item, + cbor_item_t *chunk); + +/** Creates a new definite byte string + * + * The handle is initialized to `NULL` and length to 0 + * + * @return Reference to the new bytestring item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_new_definite_bytestring(void); + +/** Creates a new indefinite byte string + * + * The chunks array is initialized to `NULL` and chunk count to 0 + * + * @return Reference to the new bytestring item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_new_indefinite_bytestring(void); + +/** Creates a new byte string and initializes it + * + * The `handle` will be copied to a newly allocated block + * + * @param handle Block of binary data + * @param length Length of `data` + * @return Reference to the new bytestring item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_build_bytestring(cbor_data handle, size_t length); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_BYTESTRINGS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.c new file mode 100644 index 00000000000..bdf3f79eee6 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "callbacks.h" + +void cbor_null_uint8_callback(void *_CBOR_UNUSED(_ctx), + uint8_t _CBOR_UNUSED(_val)) {} + +void cbor_null_uint16_callback(void *_CBOR_UNUSED(_ctx), + uint16_t _CBOR_UNUSED(_val)) {} + +void cbor_null_uint32_callback(void *_CBOR_UNUSED(_ctx), + uint32_t _CBOR_UNUSED(_val)) {} + +void cbor_null_uint64_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} + +void cbor_null_negint8_callback(void *_CBOR_UNUSED(_ctx), + uint8_t _CBOR_UNUSED(_val)) {} + +void cbor_null_negint16_callback(void *_CBOR_UNUSED(_ctx), + uint16_t _CBOR_UNUSED(_val)) {} + +void cbor_null_negint32_callback(void *_CBOR_UNUSED(_ctx), + uint32_t _CBOR_UNUSED(_val)) {} + +void cbor_null_negint64_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} + +void cbor_null_string_callback(void *_CBOR_UNUSED(_ctx), + cbor_data _CBOR_UNUSED(_val), + uint64_t _CBOR_UNUSED(_val2)) {} + +void cbor_null_string_start_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_byte_string_callback(void *_CBOR_UNUSED(_ctx), + cbor_data _CBOR_UNUSED(_val), + uint64_t _CBOR_UNUSED(_val2)) {} + +void cbor_null_byte_string_start_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_array_start_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} + +void cbor_null_indef_array_start_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_map_start_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} + +void cbor_null_indef_map_start_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_tag_callback(void *_CBOR_UNUSED(_ctx), + uint64_t _CBOR_UNUSED(_val)) {} + +void cbor_null_float2_callback(void *_CBOR_UNUSED(_ctx), + float _CBOR_UNUSED(_val)) {} + +void cbor_null_float4_callback(void *_CBOR_UNUSED(_ctx), + float _CBOR_UNUSED(_val)) {} + +void cbor_null_float8_callback(void *_CBOR_UNUSED(_ctx), + double _CBOR_UNUSED(_val)) {} + +void cbor_null_null_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_undefined_callback(void *_CBOR_UNUSED(_ctx)) {} + +void cbor_null_boolean_callback(void *_CBOR_UNUSED(_ctx), + bool _CBOR_UNUSED(_val)) {} + +void cbor_null_indef_break_callback(void *_CBOR_UNUSED(_ctx)) {} + +CBOR_EXPORT const struct cbor_callbacks cbor_empty_callbacks = { + /* Type 0 - Unsigned integers */ + .uint8 = cbor_null_uint8_callback, + .uint16 = cbor_null_uint16_callback, + .uint32 = cbor_null_uint32_callback, + .uint64 = cbor_null_uint64_callback, + + /* Type 1 - Negative integers */ + .negint8 = cbor_null_negint8_callback, + .negint16 = cbor_null_negint16_callback, + .negint32 = cbor_null_negint32_callback, + .negint64 = cbor_null_negint64_callback, + + /* Type 2 - Byte strings */ + .byte_string_start = cbor_null_byte_string_start_callback, + .byte_string = cbor_null_byte_string_callback, + + /* Type 3 - Strings */ + .string_start = cbor_null_string_start_callback, + .string = cbor_null_string_callback, + + /* Type 4 - Arrays */ + .indef_array_start = cbor_null_indef_array_start_callback, + .array_start = cbor_null_array_start_callback, + + /* Type 5 - Maps */ + .indef_map_start = cbor_null_indef_map_start_callback, + .map_start = cbor_null_map_start_callback, + + /* Type 6 - Tags */ + .tag = cbor_null_tag_callback, + + /* Type 7 - Floats & misc */ + /* Type names cannot be member names */ + .float2 = cbor_null_float2_callback, + /* 2B float is not supported in standard C */ + .float4 = cbor_null_float4_callback, + .float8 = cbor_null_float8_callback, + .undefined = cbor_null_undefined_callback, + .null = cbor_null_null_callback, + .boolean = cbor_null_boolean_callback, + + /* Shared indefinites */ + .indef_break = cbor_null_indef_break_callback, +}; diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.h new file mode 100644 index 00000000000..c7ae20568dc --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/callbacks.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_CALLBACKS_H +#define LIBCBOR_CALLBACKS_H + +#include <stdint.h> + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Callback prototype */ +typedef void (*cbor_int8_callback)(void *, uint8_t); + +/** Callback prototype */ +typedef void (*cbor_int16_callback)(void *, uint16_t); + +/** Callback prototype */ +typedef void (*cbor_int32_callback)(void *, uint32_t); + +/** Callback prototype */ +typedef void (*cbor_int64_callback)(void *, uint64_t); + +/** Callback prototype */ +typedef void (*cbor_simple_callback)(void *); + +/** Callback prototype */ +typedef void (*cbor_string_callback)(void *, cbor_data, uint64_t); + +/** Callback prototype */ +typedef void (*cbor_collection_callback)(void *, uint64_t); + +/** Callback prototype */ +typedef void (*cbor_float_callback)(void *, float); + +/** Callback prototype */ +typedef void (*cbor_double_callback)(void *, double); + +/** Callback prototype */ +typedef void (*cbor_bool_callback)(void *, bool); + +/** Callback bundle -- passed to the decoder */ +struct cbor_callbacks { + /** Unsigned int */ + cbor_int8_callback uint8; + /** Unsigned int */ + cbor_int16_callback uint16; + /** Unsigned int */ + cbor_int32_callback uint32; + /** Unsigned int */ + cbor_int64_callback uint64; + + /** Negative int */ + cbor_int64_callback negint64; + /** Negative int */ + cbor_int32_callback negint32; + /** Negative int */ + cbor_int16_callback negint16; + /** Negative int */ + cbor_int8_callback negint8; + + /** Definite byte string */ + cbor_simple_callback byte_string_start; + /** Indefinite byte string start */ + cbor_string_callback byte_string; + + /** Definite string */ + cbor_string_callback string; + /** Indefinite string start */ + cbor_simple_callback string_start; + + /** Definite array */ + cbor_simple_callback indef_array_start; + /** Indefinite array */ + cbor_collection_callback array_start; + + /** Definite map */ + cbor_simple_callback indef_map_start; + /** Indefinite map */ + cbor_collection_callback map_start; + + /** Tags */ + cbor_int64_callback tag; + + /** Half float */ + cbor_float_callback float2; + /** Single float */ + cbor_float_callback float4; + /** Double float */ + cbor_double_callback float8; + /** Undef */ + cbor_simple_callback undefined; + /** Null */ + cbor_simple_callback null; + /** Bool */ + cbor_bool_callback boolean; + + /** Indefinite item break */ + cbor_simple_callback indef_break; +}; + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_uint8_callback(void *, uint8_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_uint16_callback(void *, uint16_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_uint32_callback(void *, uint32_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_uint64_callback(void *, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_negint8_callback(void *, uint8_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_negint16_callback(void *, uint16_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_negint32_callback(void *, uint32_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_negint64_callback(void *, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_string_callback(void *, cbor_data, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_string_start_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_byte_string_callback(void *, cbor_data, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_byte_string_start_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_array_start_callback(void *, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_indef_array_start_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_map_start_callback(void *, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_indef_map_start_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_tag_callback(void *, uint64_t); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_float2_callback(void *, float); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_float4_callback(void *, float); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_float8_callback(void *, double); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_null_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_undefined_callback(void *); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_boolean_callback(void *, bool); + +/** Dummy callback implementation - does nothing */ +CBOR_EXPORT void cbor_null_indef_break_callback(void *); + +/** Dummy callback bundle - does nothing */ +CBOR_EXPORT extern const struct cbor_callbacks cbor_empty_callbacks; + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_CALLBACKS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/cbor_export.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/cbor_export.h new file mode 100644 index 00000000000..b739bb32bb6 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/cbor_export.h @@ -0,0 +1,14 @@ +/** + * DO NOT DIRECTLY MODIFY THIS FILE: + * + * The code in this file is generated from scripts/import_libcbor.py + * and any modifications should be in there. + */ + +#ifndef CBOR_EXPORT_H +#define CBOR_EXPORT_H + +/* Don't export anything from libcbor */ +#define CBOR_EXPORT + +#endif /* CBOR_EXPORT_H */ diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.c new file mode 100644 index 00000000000..efbd37ed79d --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "cbor/common.h" +#include "arrays.h" +#include "bytestrings.h" +#include "data.h" +#include "floats_ctrls.h" +#include "ints.h" +#include "maps.h" +#include "strings.h" +#include "tags.h" + +#ifdef DEBUG +bool _cbor_enable_assert = true; +#endif + +bool cbor_isa_uint(const cbor_item_t *item) { + return item->type == CBOR_TYPE_UINT; +} + +bool cbor_isa_negint(const cbor_item_t *item) { + return item->type == CBOR_TYPE_NEGINT; +} + +bool cbor_isa_bytestring(const cbor_item_t *item) { + return item->type == CBOR_TYPE_BYTESTRING; +} + +bool cbor_isa_string(const cbor_item_t *item) { + return item->type == CBOR_TYPE_STRING; +} + +bool cbor_isa_array(const cbor_item_t *item) { + return item->type == CBOR_TYPE_ARRAY; +} + +bool cbor_isa_map(const cbor_item_t *item) { + return item->type == CBOR_TYPE_MAP; +} + +bool cbor_isa_tag(const cbor_item_t *item) { + return item->type == CBOR_TYPE_TAG; +} + +bool cbor_isa_float_ctrl(const cbor_item_t *item) { + return item->type == CBOR_TYPE_FLOAT_CTRL; +} + +cbor_type cbor_typeof(const cbor_item_t *item) { return item->type; } + +bool cbor_is_int(const cbor_item_t *item) { + return cbor_isa_uint(item) || cbor_isa_negint(item); +} + +bool cbor_is_bool(const cbor_item_t *item) { + return cbor_isa_float_ctrl(item) && + (cbor_ctrl_value(item) == CBOR_CTRL_FALSE || + cbor_ctrl_value(item) == CBOR_CTRL_TRUE); +} + +bool cbor_is_null(const cbor_item_t *item) { + return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_NULL; +} + +bool cbor_is_undef(const cbor_item_t *item) { + return cbor_isa_float_ctrl(item) && cbor_ctrl_value(item) == CBOR_CTRL_UNDEF; +} + +bool cbor_is_float(const cbor_item_t *item) { + return cbor_isa_float_ctrl(item) && !cbor_float_ctrl_is_ctrl(item); +} + +cbor_item_t *cbor_incref(cbor_item_t *item) { + item->refcount++; + return item; +} + +void cbor_decref(cbor_item_t **item_ref) { + cbor_item_t *item = *item_ref; + CBOR_ASSERT(item->refcount > 0); + if (--item->refcount == 0) { + switch (item->type) { + case CBOR_TYPE_UINT: + /* Fallthrough */ + case CBOR_TYPE_NEGINT: + /* Combined allocation, freeing the item suffices */ + { break; } + case CBOR_TYPE_BYTESTRING: { + if (cbor_bytestring_is_definite(item)) { + _cbor_free(item->data); + } else { + /* We need to decref all chunks */ + cbor_item_t **handle = cbor_bytestring_chunks_handle(item); + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) + cbor_decref(&handle[i]); + _cbor_free( + ((struct cbor_indefinite_string_data *)item->data)->chunks); + _cbor_free(item->data); + } + break; + } + case CBOR_TYPE_STRING: { + if (cbor_string_is_definite(item)) { + _cbor_free(item->data); + } else { + /* We need to decref all chunks */ + cbor_item_t **handle = cbor_string_chunks_handle(item); + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) + cbor_decref(&handle[i]); + _cbor_free( + ((struct cbor_indefinite_string_data *)item->data)->chunks); + _cbor_free(item->data); + } + break; + } + case CBOR_TYPE_ARRAY: { + /* Get all items and decref them */ + cbor_item_t **handle = cbor_array_handle(item); + size_t size = cbor_array_size(item); + for (size_t i = 0; i < size; i++) + if (handle[i] != NULL) cbor_decref(&handle[i]); + _cbor_free(item->data); + break; + } + case CBOR_TYPE_MAP: { + struct cbor_pair *handle = cbor_map_handle(item); + for (size_t i = 0; i < item->metadata.map_metadata.end_ptr; + i++, handle++) { + cbor_decref(&handle->key); + if (handle->value != NULL) cbor_decref(&handle->value); + } + _cbor_free(item->data); + break; + } + case CBOR_TYPE_TAG: { + if (item->metadata.tag_metadata.tagged_item != NULL) + cbor_decref(&item->metadata.tag_metadata.tagged_item); + _cbor_free(item->data); + break; + } + case CBOR_TYPE_FLOAT_CTRL: { + /* Floats have combined allocation */ + break; + } + } + _cbor_free(item); + *item_ref = NULL; + } +} + +void cbor_intermediate_decref(cbor_item_t *item) { cbor_decref(&item); } + +size_t cbor_refcount(const cbor_item_t *item) { return item->refcount; } + +cbor_item_t *cbor_move(cbor_item_t *item) { + item->refcount--; + return item; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.h new file mode 100644 index 00000000000..1d0b426cff4 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/common.h @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_COMMON_H +#define LIBCBOR_COMMON_H + +#include <assert.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#include "cbor/cbor_export.h" +#include "cbor/configuration.h" +#include "data.h" + +#ifdef __cplusplus +extern "C" { + +/** + * C99 is not a subset of C++ -- 'restrict' qualifier is not a part of the + * language. This is a workaround to keep it in C headers -- compilers allow + * linking non-restrict signatures with restrict implementations. + * + * If you know a nicer way, please do let me know. + */ +#define CBOR_RESTRICT_POINTER + +#else + +// MSVC + C++ workaround +#define CBOR_RESTRICT_POINTER CBOR_RESTRICT_SPECIFIER + +#endif + +static const uint8_t cbor_major_version = CBOR_MAJOR_VERSION; +static const uint8_t cbor_minor_version = CBOR_MINOR_VERSION; +static const uint8_t cbor_patch_version = CBOR_PATCH_VERSION; + +#define CBOR_VERSION \ + _CBOR_TO_STR(CBOR_MAJOR_VERSION) \ + "." _CBOR_TO_STR(CBOR_MINOR_VERSION) "." _CBOR_TO_STR(CBOR_PATCH_VERSION) +#define CBOR_HEX_VERSION \ + ((CBOR_MAJOR_VERSION << 16) | (CBOR_MINOR_VERSION << 8) | CBOR_PATCH_VERSION) + +/* http://stackoverflow.com/questions/1644868/c-define-macro-for-debug-printing + */ +#ifdef DEBUG +#include <stdio.h> +#define _cbor_debug_print(fmt, ...) \ + do { \ + if (DEBUG) \ + fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, __func__, \ + __VA_ARGS__); \ + } while (0) +extern bool _cbor_enable_assert; +// Like `assert`, but can be dynamically disabled in tests to allow testing +// invalid behaviors. +#define CBOR_ASSERT(e) assert(!_cbor_enable_assert || (e)) +#define _CBOR_TEST_DISABLE_ASSERT(block) \ + do { \ + _cbor_enable_assert = false; \ + block _cbor_enable_assert = true; \ + } while (0) +#else +#define debug_print(fmt, ...) \ + do { \ + } while (0) +#define CBOR_ASSERT(e) +#define _CBOR_TEST_DISABLE_ASSERT(block) \ + do { \ + block \ + } while (0) +#endif + +#define _CBOR_TO_STR_(x) #x +#define _CBOR_TO_STR(x) _CBOR_TO_STR_(x) /* enables proper double expansion */ + +#ifdef __GNUC__ +#define _CBOR_UNUSED(x) __attribute__((__unused__)) x +// TODO(https://github.com/PJK/libcbor/issues/247): Prefer [[nodiscard]] if +// available +#define _CBOR_NODISCARD __attribute__((warn_unused_result)) +#elif defined(_MSC_VER) +#define _CBOR_UNUSED(x) __pragma(warning(suppress : 4100 4101)) x +#define _CBOR_NODISCARD +#else +#define _CBOR_UNUSED(x) x +#define _CBOR_NODISCARD +#endif + +typedef void *(*_cbor_malloc_t)(size_t); +typedef void *(*_cbor_realloc_t)(void *, size_t); +typedef void (*_cbor_free_t)(void *); + +CBOR_EXPORT extern _cbor_malloc_t _cbor_malloc; +CBOR_EXPORT extern _cbor_realloc_t _cbor_realloc; +CBOR_EXPORT extern _cbor_free_t _cbor_free; + +// Macro to short-circuit builder functions when memory allocation fails +#define _CBOR_NOTNULL(cbor_item) \ + do { \ + if (cbor_item == NULL) { \ + return NULL; \ + } \ + } while (0) + +// Macro to short-circuit builders when memory allocation of nested data fails +#define _CBOR_DEPENDENT_NOTNULL(cbor_item, pointer) \ + do { \ + if (pointer == NULL) { \ + _cbor_free(cbor_item); \ + return NULL; \ + } \ + } while (0) + +/** Sets the memory management routines to use. + * + * By default, libcbor will use the standard library `malloc`, `realloc`, and + * `free`. + * + * \rst + * .. warning:: This function modifies the global state and should therefore be + * used accordingly. Changing the memory handlers while allocated items exist + * will result in a ``free``/``malloc`` mismatch. This function is not thread + * safe with respect to both itself and all the other *libcbor* functions that + * work with the heap. + * + * .. note:: `realloc` implementation must correctly support `NULL` reallocation + * (see e.g. http://en.cppreference.com/w/c/memory/realloc) + * \endrst + * + * @param custom_malloc malloc implementation + * @param custom_realloc realloc implementation + * @param custom_free free implementation + */ +CBOR_EXPORT void cbor_set_allocs(_cbor_malloc_t custom_malloc, + _cbor_realloc_t custom_realloc, + _cbor_free_t custom_free); + +/* + * ============================================================================ + * Type manipulation + * ============================================================================ + */ + +/** Get the type of the item + * + * @param item + * @return The type + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_type cbor_typeof( + const cbor_item_t *item); /* Will be inlined iff link-time opt is enabled */ + +/* Standard CBOR Major item types */ + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item an #CBOR_TYPE_UINT? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_uint(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_NEGINT? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_negint(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_BYTESTRING? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_bytestring(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_STRING? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_string(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item an #CBOR_TYPE_ARRAY? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_array(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_MAP? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_map(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_TAG? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_tag(const cbor_item_t *item); + +/** Does the item have the appropriate major type? + * @param item the item + * @return Is the item a #CBOR_TYPE_FLOAT_CTRL? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_isa_float_ctrl(const cbor_item_t *item); + +/* Practical types with respect to their semantics (but not tag values) */ + +/** Is the item an integer, either positive or negative? + * @param item the item + * @return Is the item an integer, either positive or negative? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_int(const cbor_item_t *item); + +/** Is the item an a floating point number? + * @param item the item + * @return Is the item a floating point number? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_float(const cbor_item_t *item); + +/** Is the item an a boolean? + * @param item the item + * @return Is the item a boolean? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_bool(const cbor_item_t *item); + +/** Does this item represent `null` + * + * \rst + * .. warning:: This is in no way related to the value of the pointer. Passing a + * null pointer will most likely result in a crash. + * \endrst + * + * @param item the item + * @return Is the item (CBOR logical) null? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_null(const cbor_item_t *item); + +/** Does this item represent `undefined` + * + * \rst + * .. warning:: Care must be taken to distinguish nulls and undefined values in + * C. + * \endrst + * + * @param item the item + * @return Is the item (CBOR logical) undefined? + */ +_CBOR_NODISCARD +CBOR_EXPORT bool cbor_is_undef(const cbor_item_t *item); + +/* + * ============================================================================ + * Memory management + * ============================================================================ + */ + +/** Increases the item's reference count by one + * + * Constant complexity; items referring to this one or items being referred to + * are not updated. + * + * This function can be used to extend reference counting to client code. + * + * @param item Reference to an item + * @return The input \p item + */ +CBOR_EXPORT cbor_item_t *cbor_incref(cbor_item_t *item); + +/** Decreases the item's reference count by one, deallocating the item if needed + * + * In case the item is deallocated, the reference count of all items this item + * references will also be #cbor_decref 'ed recursively. + * + * @param item Reference to an item. Will be set to `NULL` if deallocated + */ +CBOR_EXPORT void cbor_decref(cbor_item_t **item); + +/** Decreases the item's reference count by one, deallocating the item if needed + * + * Convenience wrapper for #cbor_decref when its set-to-null behavior is not + * needed + * + * @param item Reference to an item + */ +CBOR_EXPORT void cbor_intermediate_decref(cbor_item_t *item); + +/** Get the item's reference count + * + * \rst + * .. warning:: This does *not* account for transitive references. + * \endrst + * + * @todo Add some inline examples for reference counting + * + * @param item the item + * @return the reference count + */ +_CBOR_NODISCARD +CBOR_EXPORT size_t cbor_refcount(const cbor_item_t *item); + +/** Provides CPP-like move construct + * + * Decreases the reference count by one, but does not deallocate the item even + * if its refcount reaches zero. This is useful for passing intermediate values + * to functions that increase reference count. Should only be used with + * functions that `incref` their arguments. + * + * \rst + * .. warning:: If the item is moved without correctly increasing the reference + * count afterwards, the memory will be leaked. + * \endrst + * + * @param item Reference to an item + * @return the item with reference count decreased by one + */ +_CBOR_NODISCARD +CBOR_EXPORT cbor_item_t *cbor_move(cbor_item_t *item); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_COMMON_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/configuration.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/configuration.h new file mode 100644 index 00000000000..83fe90bd356 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/configuration.h @@ -0,0 +1,46 @@ +/** + * DO NOT DIRECTLY MODIFY THIS FILE: + * + * The code in this file is generated from scripts/import_libcbor.py + * and any modifications should be in there. + */ + +#ifndef LIBCBOR_CONFIGURATION_H +#define LIBCBOR_CONFIGURATION_H + +#define CBOR_MAJOR_VERSION 0 +#define CBOR_MINOR_VERSION 11 +#define CBOR_PATCH_VERSION 0 + +#define CBOR_BUFFER_GROWTH 2 +#define CBOR_MAX_STACK_SIZE 2048 +#define CBOR_PRETTY_PRINTER 1 + +#if defined(_MSC_VER) +# define CBOR_RESTRICT_SPECIFIER +#else +# define CBOR_RESTRICT_SPECIFIER restrict +#endif + +#define CBOR_INLINE_SPECIFIER + +/* Ignore the compiler warnings for libcbor. */ +#ifdef _MSC_VER +# pragma warning(disable : 4028) +# pragma warning(disable : 4715) +# pragma warning(disable : 4232) +# pragma warning(disable : 4068) +# pragma warning(disable : 4244) +# pragma warning(disable : 4701) +# pragma warning(disable : 4703) +#endif + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wreturn-type" +#elif defined(__GNUC__) +# pragma GCC diagnostic ignored "-Wreturn-type" +# pragma GCC diagnostic ignored "-Wunknown-pragmas" +# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif + +#endif // LIBCBOR_CONFIGURATION_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/data.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/data.h new file mode 100644 index 00000000000..a12e92f20c3 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/data.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_DATA_H +#define LIBCBOR_DATA_H + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef const unsigned char* cbor_data; +typedef unsigned char* cbor_mutable_data; + +/** Specifies the Major type of ::cbor_item_t */ +typedef enum cbor_type { + CBOR_TYPE_UINT /** 0 - positive integers */ + , + CBOR_TYPE_NEGINT /** 1 - negative integers*/ + , + CBOR_TYPE_BYTESTRING /** 2 - byte strings */ + , + CBOR_TYPE_STRING /** 3 - strings */ + , + CBOR_TYPE_ARRAY /** 4 - arrays */ + , + CBOR_TYPE_MAP /** 5 - maps */ + , + CBOR_TYPE_TAG /** 6 - tags */ + , + CBOR_TYPE_FLOAT_CTRL /** 7 - decimals and special values (true, false, nil, + ...) */ +} cbor_type; + +/** Possible decoding errors */ +typedef enum { + CBOR_ERR_NONE, + CBOR_ERR_NOTENOUGHDATA, + CBOR_ERR_NODATA, + // TODO: Should be "malformed" or at least "malformatted". Retained for + // backwards compatibility. + CBOR_ERR_MALFORMATED, + CBOR_ERR_MEMERROR /** Memory error - item allocation failed. Is it too big for + your allocator? */ + , + CBOR_ERR_SYNTAXERROR /** Stack parsing algorithm failed */ +} cbor_error_code; + +/** Possible widths of #CBOR_TYPE_UINT items */ +typedef enum { + CBOR_INT_8, + CBOR_INT_16, + CBOR_INT_32, + CBOR_INT_64 +} cbor_int_width; + +/** Possible widths of #CBOR_TYPE_FLOAT_CTRL items */ +typedef enum { + CBOR_FLOAT_0 /** Internal use - ctrl and special values */ + , + CBOR_FLOAT_16 /** Half float */ + , + CBOR_FLOAT_32 /** Single float */ + , + CBOR_FLOAT_64 /** Double */ +} cbor_float_width; + +/** Metadata for dynamically sized types */ +typedef enum { + _CBOR_METADATA_DEFINITE, + _CBOR_METADATA_INDEFINITE +} _cbor_dst_metadata; + +/** Semantic mapping for CTRL simple values */ +typedef enum { + CBOR_CTRL_NONE = 0, + CBOR_CTRL_FALSE = 20, + CBOR_CTRL_TRUE = 21, + CBOR_CTRL_NULL = 22, + CBOR_CTRL_UNDEF = 23 +} _cbor_ctrl; + +// Metadata items use size_t (instead of uint64_t) because items in memory take +// up at least 1B per entry or string byte, so if size_t is narrower than +// uint64_t, we wouldn't be able to create them in the first place and can save +// some space. + +/** Integers specific metadata */ +struct _cbor_int_metadata { + cbor_int_width width; +}; + +/** Bytestrings specific metadata */ +struct _cbor_bytestring_metadata { + size_t length; + _cbor_dst_metadata type; +}; + +/** Strings specific metadata */ +struct _cbor_string_metadata { + size_t length; + size_t codepoint_count; /* Sum of chunks' codepoint_counts for indefinite + strings */ + _cbor_dst_metadata type; +}; + +/** Arrays specific metadata */ +struct _cbor_array_metadata { + size_t allocated; + size_t end_ptr; + _cbor_dst_metadata type; +}; + +/** Maps specific metadata */ +struct _cbor_map_metadata { + size_t allocated; + size_t end_ptr; + _cbor_dst_metadata type; +}; + +/** Arrays specific metadata + * + * The pointer is included - cbor_item_metadata is + * 2 * sizeof(size_t) + sizeof(_cbor_string_type_metadata), + * lets use the space + */ +struct _cbor_tag_metadata { + struct cbor_item_t* tagged_item; + uint64_t value; +}; + +/** Floats specific metadata - includes CTRL values */ +struct _cbor_float_ctrl_metadata { + cbor_float_width width; + uint8_t ctrl; +}; + +/** Raw memory casts helper */ +union _cbor_float_helper { + float as_float; + uint32_t as_uint; +}; + +/** Raw memory casts helper */ +union _cbor_double_helper { + double as_double; + uint64_t as_uint; +}; + +/** Union of metadata across all possible types - discriminated in #cbor_item_t + */ +union cbor_item_metadata { + struct _cbor_int_metadata int_metadata; + struct _cbor_bytestring_metadata bytestring_metadata; + struct _cbor_string_metadata string_metadata; + struct _cbor_array_metadata array_metadata; + struct _cbor_map_metadata map_metadata; + struct _cbor_tag_metadata tag_metadata; + struct _cbor_float_ctrl_metadata float_ctrl_metadata; +}; + +/** The item handle */ +typedef struct cbor_item_t { + /** Discriminated by type */ + union cbor_item_metadata metadata; + /** Reference count - initialize to 0 */ + size_t refcount; + /** Major type discriminator */ + cbor_type type; + /** Raw data block - interpretation depends on metadata */ + unsigned char* data; +} cbor_item_t; + +/** Defines cbor_item_t#data structure for indefinite strings and bytestrings + * + * Used to cast the raw representation for a sane manipulation + */ +struct cbor_indefinite_string_data { + size_t chunk_count; + size_t chunk_capacity; + cbor_item_t** chunks; +}; + +/** High-level decoding error */ +struct cbor_error { + /** Approximate position */ + size_t position; + /** Description */ + cbor_error_code code; +}; + +/** Simple pair of items for use in maps */ +struct cbor_pair { + cbor_item_t *key, *value; +}; + +/** High-level decoding result */ +struct cbor_load_result { + /** Error indicator */ + struct cbor_error error; + /** Number of bytes read */ + size_t read; +}; + +/** Streaming decoder result - status */ +enum cbor_decoder_status { + /** Decoding finished successfully (a callback has been invoked) + * + * Note that this does *not* mean that the buffer has been fully decoded; + * there may still be unread bytes for which no callback has been involved. + */ + CBOR_DECODER_FINISHED, + /** Not enough data to invoke a callback */ + // TODO: The name is inconsistent with CBOR_ERR_NOTENOUGHDATA. Retained for + // backwards compatibility. + CBOR_DECODER_NEDATA, + /** Bad data (reserved MTB, malformed value, etc.) */ + CBOR_DECODER_ERROR +}; + +/** Streaming decoder result */ +struct cbor_decoder_result { + /** Input bytes read/consumed + * + * If this is less than the size of input buffer, the client will likely + * resume parsing starting at the next byte (e.g. `buffer + result.read`). + * + * Set to 0 if the #status is not #CBOR_DECODER_FINISHED. + */ + size_t read; + + /** The decoding status */ + enum cbor_decoder_status status; + + /** Number of bytes in the input buffer needed to resume parsing + * + * Set to 0 unless the result status is #CBOR_DECODER_NEDATA. If it is, then: + * - If at least one byte was passed, #required will be set to the minimum + * number of bytes needed to invoke a decoded callback on the current + * prefix. + * + * For example: Attempting to decode a 1B buffer containing `0x19` will + * set #required to 3 as `0x19` signals a 2B integer item, so we need at + * least 3B to continue (the `0x19` MTB byte and two bytes of data needed + * to invoke #cbor_callbacks.uint16). + * + * - If there was no data at all, #read will always be set to 1 + */ + size_t required; +}; + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_DATA_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.c new file mode 100644 index 00000000000..9d931d17570 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "encoding.h" +#include "internal/encoders.h" + +size_t cbor_encode_uint8(uint8_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint8(value, buffer, buffer_size, 0x00); +} + +size_t cbor_encode_uint16(uint16_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint16(value, buffer, buffer_size, 0x00); +} + +size_t cbor_encode_uint32(uint32_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint32(value, buffer, buffer_size, 0x00); +} + +size_t cbor_encode_uint64(uint64_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint64(value, buffer, buffer_size, 0x00); +} + +size_t cbor_encode_uint(uint64_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint(value, buffer, buffer_size, 0x00); +} + +size_t cbor_encode_negint8(uint8_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint8(value, buffer, buffer_size, 0x20); +} + +size_t cbor_encode_negint16(uint16_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint16(value, buffer, buffer_size, 0x20); +} + +size_t cbor_encode_negint32(uint32_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint32(value, buffer, buffer_size, 0x20); +} + +size_t cbor_encode_negint64(uint64_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint64(value, buffer, buffer_size, 0x20); +} + +size_t cbor_encode_negint(uint64_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint(value, buffer, buffer_size, 0x20); +} + +size_t cbor_encode_bytestring_start(size_t length, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x40); +} + +size_t _cbor_encode_byte(uint8_t value, unsigned char *buffer, + size_t buffer_size) { + if (buffer_size >= 1) { + buffer[0] = value; + return 1; + } else + return 0; +} + +size_t cbor_encode_indef_bytestring_start(unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_byte(0x5F, buffer, buffer_size); +} + +size_t cbor_encode_string_start(size_t length, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x60); +} + +size_t cbor_encode_indef_string_start(unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_byte(0x7F, buffer, buffer_size); +} + +size_t cbor_encode_array_start(size_t length, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0x80); +} + +size_t cbor_encode_indef_array_start(unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_byte(0x9F, buffer, buffer_size); +} + +size_t cbor_encode_map_start(size_t length, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint((size_t)length, buffer, buffer_size, 0xA0); +} + +size_t cbor_encode_indef_map_start(unsigned char *buffer, size_t buffer_size) { + return _cbor_encode_byte(0xBF, buffer, buffer_size); +} + +size_t cbor_encode_tag(uint64_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint(value, buffer, buffer_size, 0xC0); +} + +size_t cbor_encode_bool(bool value, unsigned char *buffer, size_t buffer_size) { + return value ? _cbor_encode_byte(0xF5, buffer, buffer_size) + : _cbor_encode_byte(0xF4, buffer, buffer_size); +} + +size_t cbor_encode_null(unsigned char *buffer, size_t buffer_size) { + return _cbor_encode_byte(0xF6, buffer, buffer_size); +} + +size_t cbor_encode_undef(unsigned char *buffer, size_t buffer_size) { + return _cbor_encode_byte(0xF7, buffer, buffer_size); +} + +size_t cbor_encode_half(float value, unsigned char *buffer, + size_t buffer_size) { + /* Assuming value is normalized */ + uint32_t val = ((union _cbor_float_helper){.as_float = value}).as_uint; + uint16_t res; + uint8_t exp = (uint8_t)((val & 0x7F800000u) >> + 23u); /* 0b0111_1111_1000_0000_0000_0000_0000_0000 */ + uint32_t mant = + val & 0x7FFFFFu; /* 0b0000_0000_0111_1111_1111_1111_1111_1111 */ + if (exp == 0xFF) { /* Infinity or NaNs */ + if (value != value) { + // We discard information bits in half-float NaNs. This is + // not required for the core CBOR protocol (it is only a suggestion in + // Section 3.9). + // See https://github.com/PJK/libcbor/issues/215 + res = (uint16_t)0x007e00; + } else { + // If the mantissa is non-zero, we have a NaN, but those are handled + // above. See + // https://en.wikipedia.org/wiki/Half-precision_floating-point_format + CBOR_ASSERT(mant == 0u); + res = (uint16_t)((val & 0x80000000u) >> 16u | 0x7C00u); + } + } else if (exp == 0x00) { /* Zeroes or subnorms */ + res = (uint16_t)((val & 0x80000000u) >> 16u | mant >> 13u); + } else { /* Normal numbers */ + int8_t logical_exp = (int8_t)(exp - 127); + CBOR_ASSERT(logical_exp == exp - 127); + + // Now we know that 2^exp <= 0 logically + if (logical_exp < -24) { + /* No unambiguous representation exists, this float is not a half float + and is too small to be represented using a half, round off to zero. + Consistent with the reference implementation. */ + res = 0; + } else if (logical_exp < -14) { + /* Offset the remaining decimal places by shifting the significand, the + value is lost. This is an implementation decision that works around the + absence of standard half-float in the language. */ + res = (uint16_t)((val & 0x80000000u) >> 16u) | // Extract sign bit + ((uint16_t)(1u << (24u + logical_exp)) + + (uint16_t)(((mant >> (-logical_exp - 2)) + 1) >> + 1)); // Round half away from zero for simplicity + } else { + res = (uint16_t)((val & 0x80000000u) >> 16u | + ((((uint8_t)logical_exp) + 15u) << 10u) | + (uint16_t)(mant >> 13u)); + } + } + return _cbor_encode_uint16(res, buffer, buffer_size, 0xE0); +} + +size_t cbor_encode_single(float value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint32( + ((union _cbor_float_helper){.as_float = value}).as_uint, buffer, + buffer_size, 0xE0); +} + +size_t cbor_encode_double(double value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint64( + ((union _cbor_double_helper){.as_double = value}).as_uint, buffer, + buffer_size, 0xE0); +} + +size_t cbor_encode_break(unsigned char *buffer, size_t buffer_size) { + return _cbor_encode_byte(0xFF, buffer, buffer_size); +} + +size_t cbor_encode_ctrl(uint8_t value, unsigned char *buffer, + size_t buffer_size) { + return _cbor_encode_uint8(value, buffer, buffer_size, 0xE0); +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.h new file mode 100644 index 00000000000..bcc04f8a98e --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/encoding.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_ENCODING_H +#define LIBCBOR_ENCODING_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * All cbor_encode_* methods take 2 or 3 arguments: + * - a logical `value` to encode (except for trivial items such as NULLs) + * - an output `buffer` pointer + * - a `buffer_size` specification + * + * They serialize the `value` into one or more bytes and write the bytes to the + * output `buffer` and return either the number of bytes written, or 0 if the + * `buffer_size` was too small to small to fit the serialized value (in which + * case it is not modified). + */ + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint8(uint8_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint16(uint16_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint32(uint32_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint64(uint64_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_uint(uint64_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint8(uint8_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint16(uint16_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint32(uint32_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint64(uint64_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_negint(uint64_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_bytestring_start(size_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_bytestring_start(unsigned char *, size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_string_start(size_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_string_start(unsigned char *, size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_array_start(size_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_encode_indef_array_start(unsigned char *, size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_map_start(size_t, + unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_indef_map_start(unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_tag(uint64_t, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_bool(bool, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_null(unsigned char *, size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_undef(unsigned char *, size_t); + +/** Encodes a half-precision float + * + * Since there is no native representation or semantics for half floats + * in the language, we use single-precision floats, as every value that + * can be expressed as a half-float can also be expressed as a float. + * + * This however means that not all floats passed to this function can be + * unambiguously encoded. The behavior is as follows: + * - Infinity, NaN are preserved + * - Zero is preserved + * - Denormalized numbers keep their sign bit and 10 most significant bit of + * the significand + * - All other numbers + * - If the logical value of the exponent is < -24, the output is zero + * - If the logical value of the exponent is between -23 and -14, the output + * is cut off to represent the 'magnitude' of the input, by which we + * mean (-1)^{signbit} x 1.0e{exponent}. The value in the significand is + * lost. + * - In all other cases, the sign bit, the exponent, and 10 most significant + * bits of the significand are kept + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_half(float, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_single(float, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_double(double, unsigned char *, + size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_break(unsigned char *, size_t); + +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_encode_ctrl(uint8_t, unsigned char *, + size_t); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_ENCODING_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.c new file mode 100644 index 00000000000..57bf477d4d3 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "floats_ctrls.h" +#include <math.h> +#include "assert.h" + +cbor_float_width cbor_float_get_width(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + return item->metadata.float_ctrl_metadata.width; +} + +uint8_t cbor_ctrl_value(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0); + return item->metadata.float_ctrl_metadata.ctrl; +} + +bool cbor_float_ctrl_is_ctrl(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + return cbor_float_get_width(item) == CBOR_FLOAT_0; +} + +float cbor_float_get_float2(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16); + return *(float *)item->data; +} + +float cbor_float_get_float4(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32); + return *(float *)item->data; +} + +double cbor_float_get_float8(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64); + return *(double *)item->data; +} + +double cbor_float_get_float(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_float(item)); + // cppcheck-suppress missingReturn + switch (cbor_float_get_width(item)) { + case CBOR_FLOAT_0: + return NAN; + case CBOR_FLOAT_16: + return cbor_float_get_float2(item); + case CBOR_FLOAT_32: + return cbor_float_get_float4(item); + case CBOR_FLOAT_64: + return cbor_float_get_float8(item); + } +} + +bool cbor_get_bool(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_bool(item)); + return item->metadata.float_ctrl_metadata.ctrl == CBOR_CTRL_TRUE; +} + +void cbor_set_float2(cbor_item_t *item, float value) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_16); + *((float *)item->data) = value; +} + +void cbor_set_float4(cbor_item_t *item, float value) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_32); + *((float *)item->data) = value; +} + +void cbor_set_float8(cbor_item_t *item, double value) { + CBOR_ASSERT(cbor_is_float(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_64); + *((double *)item->data) = value; +} + +void cbor_set_ctrl(cbor_item_t *item, uint8_t value) { + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + CBOR_ASSERT(cbor_float_get_width(item) == CBOR_FLOAT_0); + item->metadata.float_ctrl_metadata.ctrl = value; +} + +void cbor_set_bool(cbor_item_t *item, bool value) { + CBOR_ASSERT(cbor_is_bool(item)); + item->metadata.float_ctrl_metadata.ctrl = + value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE; +} + +cbor_item_t *cbor_new_ctrl(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .type = CBOR_TYPE_FLOAT_CTRL, + .data = NULL, + .refcount = 1, + .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_0, + .ctrl = CBOR_CTRL_NONE}}}; + return item; +} + +cbor_item_t *cbor_new_float2(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .type = CBOR_TYPE_FLOAT_CTRL, + .data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_16}}}; + return item; +} + +cbor_item_t *cbor_new_float4(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .type = CBOR_TYPE_FLOAT_CTRL, + .data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_32}}}; + return item; +} + +cbor_item_t *cbor_new_float8(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 8); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .type = CBOR_TYPE_FLOAT_CTRL, + .data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.float_ctrl_metadata = {.width = CBOR_FLOAT_64}}}; + return item; +} + +cbor_item_t *cbor_new_null(void) { + cbor_item_t *item = cbor_new_ctrl(); + _CBOR_NOTNULL(item); + cbor_set_ctrl(item, CBOR_CTRL_NULL); + return item; +} + +cbor_item_t *cbor_new_undef(void) { + cbor_item_t *item = cbor_new_ctrl(); + _CBOR_NOTNULL(item); + cbor_set_ctrl(item, CBOR_CTRL_UNDEF); + return item; +} + +cbor_item_t *cbor_build_bool(bool value) { + return cbor_build_ctrl(value ? CBOR_CTRL_TRUE : CBOR_CTRL_FALSE); +} + +cbor_item_t *cbor_build_float2(float value) { + cbor_item_t *item = cbor_new_float2(); + _CBOR_NOTNULL(item); + cbor_set_float2(item, value); + return item; +} + +cbor_item_t *cbor_build_float4(float value) { + cbor_item_t *item = cbor_new_float4(); + _CBOR_NOTNULL(item); + cbor_set_float4(item, value); + return item; +} + +cbor_item_t *cbor_build_float8(double value) { + cbor_item_t *item = cbor_new_float8(); + _CBOR_NOTNULL(item); + cbor_set_float8(item, value); + return item; +} + +cbor_item_t *cbor_build_ctrl(uint8_t value) { + cbor_item_t *item = cbor_new_ctrl(); + _CBOR_NOTNULL(item); + cbor_set_ctrl(item, value); + return item; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.h new file mode 100644 index 00000000000..335eab8328b --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/floats_ctrls.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_FLOATS_CTRLS_H +#define LIBCBOR_FLOATS_CTRLS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * Float manipulation + * ============================================================================ + */ + +/** Is this a ctrl value? + * + * @param item A float or ctrl item + * @return Is this a ctrl value? + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_float_ctrl_is_ctrl( + const cbor_item_t *item); + +/** Get the float width + * + * @param item A float or ctrl item + * @return The width. + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_float_width +cbor_float_get_width(const cbor_item_t *item); + +/** Get a half precision float + * + * The item must have the corresponding width + * + * @param item A half precision float + * @return half precision value + */ +_CBOR_NODISCARD CBOR_EXPORT float cbor_float_get_float2( + const cbor_item_t *item); + +/** Get a single precision float + * + * The item must have the corresponding width + * + * @param item A single precision float + * @return single precision value + */ +_CBOR_NODISCARD CBOR_EXPORT float cbor_float_get_float4( + const cbor_item_t *item); + +/** Get a double precision float + * + * The item must have the corresponding width + * + * @param item A double precision float + * @return double precision value + */ +_CBOR_NODISCARD CBOR_EXPORT double cbor_float_get_float8( + const cbor_item_t *item); + +/** Get the float value represented as double + * + * Can be used regardless of the width. + * + * @param item Any float + * @return double precision value + */ +_CBOR_NODISCARD CBOR_EXPORT double cbor_float_get_float( + const cbor_item_t *item); + +/** Get value from a boolean ctrl item + * + * @param item A ctrl item + * @return boolean value + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_get_bool(const cbor_item_t *item); + +/** Constructs a new ctrl item + * + * The width cannot be changed once the item is created + * + * @return Reference to the new ctrl item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_ctrl(void); + +/** Constructs a new float item + * + * The width cannot be changed once the item is created + * + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float2(void); + +/** Constructs a new float item + * + * The width cannot be changed once the item is created + * + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float4(void); + +/** Constructs a new float item + * + * The width cannot be changed once the item is created + * + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_float8(void); + +/** Constructs new null ctrl item + * + * @return Reference to the new null item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_null(void); + +/** Constructs new undef ctrl item + * + * @return Reference to the new undef item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_undef(void); + +/** Constructs new boolean ctrl item + * + * @param value The value to use + * @return Reference to the new boolean item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_bool(bool value); + +/** Assign a control value + * + * \rst + * .. warning:: It is possible to produce an invalid CBOR value by assigning a + * invalid value using this mechanism. Please consult the standard before use. + * \endrst + * + * @param item A ctrl item + * @param value The simple value to assign. Please consult the standard for + * allowed values + */ +CBOR_EXPORT void cbor_set_ctrl(cbor_item_t *item, uint8_t value); + +/** Assign a boolean value to a boolean ctrl item + * + * @param item A ctrl item + * @param value The simple value to assign. + */ +CBOR_EXPORT void cbor_set_bool(cbor_item_t *item, bool value); + +/** Assigns a float value + * + * @param item A half precision float + * @param value The value to assign + */ +CBOR_EXPORT void cbor_set_float2(cbor_item_t *item, float value); + +/** Assigns a float value + * + * @param item A single precision float + * @param value The value to assign + */ +CBOR_EXPORT void cbor_set_float4(cbor_item_t *item, float value); + +/** Assigns a float value + * + * @param item A double precision float + * @param value The value to assign + */ +CBOR_EXPORT void cbor_set_float8(cbor_item_t *item, double value); + +/** Reads the control value + * + * @param item A ctrl item + * @return the simple value + */ +_CBOR_NODISCARD CBOR_EXPORT uint8_t cbor_ctrl_value(const cbor_item_t *item); + +/** Constructs a new float + * + * @param value the value to use + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float2(float value); + +/** Constructs a new float + * + * @param value the value to use + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float4(float value); + +/** Constructs a new float + * + * @param value the value to use + * @return Reference to the new float item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_float8(double value); + +/** Constructs a ctrl item + * + * @param value the value to use + * @return Reference to the new ctrl item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_ctrl(uint8_t value); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_FLOATS_CTRLS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.c new file mode 100644 index 00000000000..257cef3adbd --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "builder_callbacks.h" + +#include <string.h> + +#include "../arrays.h" +#include "../bytestrings.h" +#include "../common.h" +#include "../floats_ctrls.h" +#include "../ints.h" +#include "../maps.h" +#include "../strings.h" +#include "../tags.h" +#include "unicode.h" + +// `_cbor_builder_append` takes ownership of `item`. If adding the item to +// parent container fails, `item` will be deallocated to prevent memory. +void _cbor_builder_append(cbor_item_t *item, + struct _cbor_decoder_context *ctx) { + if (ctx->stack->size == 0) { + /* Top level item */ + ctx->root = item; + return; + } + /* Part of a bigger structure */ + switch (ctx->stack->top->item->type) { + // Handle Arrays and Maps since they can contain subitems of any type. + // Byte/string construction from chunks is handled in the respective chunk + // handlers. + case CBOR_TYPE_ARRAY: { + if (cbor_array_is_definite(ctx->stack->top->item)) { + // We don't need an explicit check for whether the item still belongs + // into this array because if there are extra items, they will cause a + // syntax error when decoded. + CBOR_ASSERT(ctx->stack->top->subitems > 0); + // This should never happen since the definite array should be + // preallocated for the expected number of items. + if (!cbor_array_push(ctx->stack->top->item, item)) { + ctx->creation_failed = true; + cbor_decref(&item); + break; + } + cbor_decref(&item); + ctx->stack->top->subitems--; + if (ctx->stack->top->subitems == 0) { + cbor_item_t *stack_item = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(stack_item, ctx); + } + } else { + /* Indefinite array, don't bother with subitems */ + if (!cbor_array_push(ctx->stack->top->item, item)) { + ctx->creation_failed = true; + } + cbor_decref(&item); + } + break; + } + case CBOR_TYPE_MAP: { + // Handle both definite and indefinite maps the same initially. + // Note: We use 0 and 1 subitems to distinguish between keys and values in + // indefinite items + if (ctx->stack->top->subitems % 2) { + // Odd record, this is a value. + ctx->creation_failed = + !_cbor_map_add_value(ctx->stack->top->item, item); + // Adding a value never fails since the memory is allocated when the + // key is added + CBOR_ASSERT(!ctx->creation_failed); + } else { + // Even record, this is a key. + if (!_cbor_map_add_key(ctx->stack->top->item, item)) { + ctx->creation_failed = true; + cbor_decref(&item); + break; + } + } + cbor_decref(&item); + if (cbor_map_is_definite(ctx->stack->top->item)) { + CBOR_ASSERT(ctx->stack->top->subitems > 0); + ctx->stack->top->subitems--; + if (ctx->stack->top->subitems == 0) { + cbor_item_t *map_entry = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(map_entry, ctx); + } + } else { + ctx->stack->top->subitems ^= + 1; /* Flip the indicator for indefinite items */ + } + break; + } + case CBOR_TYPE_TAG: { + CBOR_ASSERT(ctx->stack->top->subitems == 1); + cbor_tag_set_item(ctx->stack->top->item, item); + cbor_decref(&item); /* Give up on our reference */ + cbor_item_t *tagged_item = ctx->stack->top->item; + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(tagged_item, ctx); + break; + } + // We have an item to append but nothing to append it to. + default: { + cbor_decref(&item); + ctx->syntax_error = true; + } + } +} + +#define CHECK_RES(ctx, res) \ + do { \ + if (res == NULL) { \ + ctx->creation_failed = true; \ + return; \ + } \ + } while (0) + +// Check that the length fits into size_t. If not, we cannot possibly allocate +// the required memory and should fail fast. +#define CHECK_LENGTH(ctx, length) \ + do { \ + if (length > SIZE_MAX) { \ + ctx->creation_failed = true; \ + return; \ + } \ + } while (0) + +#define PUSH_CTX_STACK(ctx, res, subitems) \ + do { \ + if (_cbor_stack_push(ctx->stack, res, subitems) == NULL) { \ + cbor_decref(&res); \ + ctx->creation_failed = true; \ + } \ + } while (0) + +void cbor_builder_uint8_callback(void *context, uint8_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int8(); + CHECK_RES(ctx, res); + cbor_mark_uint(res); + cbor_set_uint8(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_uint16_callback(void *context, uint16_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int16(); + CHECK_RES(ctx, res); + cbor_mark_uint(res); + cbor_set_uint16(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_uint32_callback(void *context, uint32_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int32(); + CHECK_RES(ctx, res); + cbor_mark_uint(res); + cbor_set_uint32(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_uint64_callback(void *context, uint64_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int64(); + CHECK_RES(ctx, res); + cbor_mark_uint(res); + cbor_set_uint64(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_negint8_callback(void *context, uint8_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int8(); + CHECK_RES(ctx, res); + cbor_mark_negint(res); + cbor_set_uint8(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_negint16_callback(void *context, uint16_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int16(); + CHECK_RES(ctx, res); + cbor_mark_negint(res); + cbor_set_uint16(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_negint32_callback(void *context, uint32_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int32(); + CHECK_RES(ctx, res); + cbor_mark_negint(res); + cbor_set_uint32(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_negint64_callback(void *context, uint64_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_int64(); + CHECK_RES(ctx, res); + cbor_mark_negint(res); + cbor_set_uint64(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_byte_string_callback(void *context, cbor_data data, + uint64_t length) { + struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, length); + unsigned char *new_handle = _cbor_malloc(length); + if (new_handle == NULL) { + ctx->creation_failed = true; + return; + } + + memcpy(new_handle, data, length); + cbor_item_t *new_chunk = cbor_new_definite_bytestring(); + + if (new_chunk == NULL) { + _cbor_free(new_handle); + ctx->creation_failed = true; + return; + } + + cbor_bytestring_set_handle(new_chunk, new_handle, length); + + // If an indef bytestring is on the stack, extend it (if it were closed, it + // would have been popped). Handle any syntax errors upstream. + if (ctx->stack->size > 0 && cbor_isa_bytestring(ctx->stack->top->item) && + cbor_bytestring_is_indefinite(ctx->stack->top->item)) { + if (!cbor_bytestring_add_chunk(ctx->stack->top->item, new_chunk)) { + ctx->creation_failed = true; + } + cbor_decref(&new_chunk); + } else { + _cbor_builder_append(new_chunk, ctx); + } +} + +void cbor_builder_byte_string_start_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_indefinite_bytestring(); + CHECK_RES(ctx, res); + PUSH_CTX_STACK(ctx, res, 0); +} + +void cbor_builder_string_callback(void *context, cbor_data data, + uint64_t length) { + struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, length); + + unsigned char *new_handle = _cbor_malloc(length); + if (new_handle == NULL) { + ctx->creation_failed = true; + return; + } + + memcpy(new_handle, data, length); + cbor_item_t *new_chunk = cbor_new_definite_string(); + if (new_chunk == NULL) { + _cbor_free(new_handle); + ctx->creation_failed = true; + return; + } + cbor_string_set_handle(new_chunk, new_handle, length); + + // If an indef string is on the stack, extend it (if it were closed, it would + // have been popped). Handle any syntax errors upstream. + if (ctx->stack->size > 0 && cbor_isa_string(ctx->stack->top->item) && + cbor_string_is_indefinite(ctx->stack->top->item)) { + if (!cbor_string_add_chunk(ctx->stack->top->item, new_chunk)) { + ctx->creation_failed = true; + } + cbor_decref(&new_chunk); + } else { + _cbor_builder_append(new_chunk, ctx); + } +} + +void cbor_builder_string_start_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_indefinite_string(); + CHECK_RES(ctx, res); + PUSH_CTX_STACK(ctx, res, 0); +} + +void cbor_builder_array_start_callback(void *context, uint64_t size) { + struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, size); + cbor_item_t *res = cbor_new_definite_array(size); + CHECK_RES(ctx, res); + if (size > 0) { + PUSH_CTX_STACK(ctx, res, size); + } else { + _cbor_builder_append(res, ctx); + } +} + +void cbor_builder_indef_array_start_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_indefinite_array(); + CHECK_RES(ctx, res); + PUSH_CTX_STACK(ctx, res, 0); +} + +void cbor_builder_indef_map_start_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_indefinite_map(); + CHECK_RES(ctx, res); + PUSH_CTX_STACK(ctx, res, 0); +} + +void cbor_builder_map_start_callback(void *context, uint64_t size) { + struct _cbor_decoder_context *ctx = context; + CHECK_LENGTH(ctx, size); + cbor_item_t *res = cbor_new_definite_map(size); + CHECK_RES(ctx, res); + if (size > 0) { + PUSH_CTX_STACK(ctx, res, size * 2); + } else { + _cbor_builder_append(res, ctx); + } +} + +/** + * Is the (partially constructed) item indefinite? + */ +bool _cbor_is_indefinite(cbor_item_t *item) { + switch (item->type) { + case CBOR_TYPE_BYTESTRING: + return cbor_bytestring_is_indefinite(item); + case CBOR_TYPE_STRING: + return cbor_string_is_indefinite(item); + case CBOR_TYPE_ARRAY: + return cbor_array_is_indefinite(item); + case CBOR_TYPE_MAP: + return cbor_map_is_indefinite(item); + default: + // Should never happen since a non-nested item cannot be on top of the + // stack. + return false; + } +} + +void cbor_builder_indef_break_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + /* There must be an item to break out of*/ + if (ctx->stack->size > 0) { + cbor_item_t *item = ctx->stack->top->item; + if (_cbor_is_indefinite( + item) && /* Only indefinite items can be terminated by 0xFF */ + /* Special case: we cannot append up if an indefinite map is incomplete + (we are expecting a value). */ + (item->type != CBOR_TYPE_MAP || ctx->stack->top->subitems % 2 == 0)) { + _cbor_stack_pop(ctx->stack); + _cbor_builder_append(item, ctx); + return; + } + } + + ctx->syntax_error = true; +} + +void cbor_builder_float2_callback(void *context, float value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_float2(); + CHECK_RES(ctx, res); + cbor_set_float2(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_float4_callback(void *context, float value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_float4(); + CHECK_RES(ctx, res); + cbor_set_float4(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_float8_callback(void *context, double value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_float8(); + CHECK_RES(ctx, res); + cbor_set_float8(res, value); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_null_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_null(); + CHECK_RES(ctx, res); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_undefined_callback(void *context) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_undef(); + CHECK_RES(ctx, res); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_boolean_callback(void *context, bool value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_build_bool(value); + CHECK_RES(ctx, res); + _cbor_builder_append(res, ctx); +} + +void cbor_builder_tag_callback(void *context, uint64_t value) { + struct _cbor_decoder_context *ctx = context; + cbor_item_t *res = cbor_new_tag(value); + CHECK_RES(ctx, res); + PUSH_CTX_STACK(ctx, res, 1); +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.h new file mode 100644 index 00000000000..7893960e413 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/builder_callbacks.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_BUILDER_CALLBACKS_H +#define LIBCBOR_BUILDER_CALLBACKS_H + +#include "../callbacks.h" +#include "cbor/common.h" +#include "stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** High-level decoding context */ +struct _cbor_decoder_context { + /** Callback creating the last item has failed */ + bool creation_failed; + /** Stack expectation mismatch */ + bool syntax_error; + cbor_item_t *root; + struct _cbor_stack *stack; +}; + +/** Internal helper: Append item to the top of the stack while handling errors. + */ +void _cbor_builder_append(cbor_item_t *item, struct _cbor_decoder_context *ctx); + +void cbor_builder_uint8_callback(void *, uint8_t); + +void cbor_builder_uint16_callback(void *, uint16_t); + +void cbor_builder_uint32_callback(void *, uint32_t); + +void cbor_builder_uint64_callback(void *, uint64_t); + +void cbor_builder_negint8_callback(void *, uint8_t); + +void cbor_builder_negint16_callback(void *, uint16_t); + +void cbor_builder_negint32_callback(void *, uint32_t); + +void cbor_builder_negint64_callback(void *, uint64_t); + +void cbor_builder_string_callback(void *, cbor_data, uint64_t); + +void cbor_builder_string_start_callback(void *); + +void cbor_builder_byte_string_callback(void *, cbor_data, uint64_t); + +void cbor_builder_byte_string_start_callback(void *); + +void cbor_builder_array_start_callback(void *, uint64_t); + +void cbor_builder_indef_array_start_callback(void *); + +void cbor_builder_map_start_callback(void *, uint64_t); + +void cbor_builder_indef_map_start_callback(void *); + +void cbor_builder_tag_callback(void *, uint64_t); + +void cbor_builder_float2_callback(void *, float); + +void cbor_builder_float4_callback(void *, float); + +void cbor_builder_float8_callback(void *, double); + +void cbor_builder_null_callback(void *); + +void cbor_builder_undefined_callback(void *); + +void cbor_builder_boolean_callback(void *, bool); + +void cbor_builder_indef_break_callback(void *); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_BUILDER_CALLBACKS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.c new file mode 100644 index 00000000000..49d4d7f33d2 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "encoders.h" +#include <string.h> + +size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset) { + if (value <= 23) { + if (buffer_size >= 1) { + buffer[0] = value + offset; + return 1; + } + } else { + if (buffer_size >= 2) { + buffer[0] = 0x18 + offset; + buffer[1] = value; + return 2; + } + } + return 0; +} + +size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset) { + if (buffer_size >= 3) { + buffer[0] = 0x19 + offset; + +#ifdef IS_BIG_ENDIAN + memcpy(buffer + 1, &value, 2); +#else + buffer[1] = (unsigned char)(value >> 8); + buffer[2] = (unsigned char)value; +#endif + + return 3; + } else + return 0; +} + +size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset) { + if (buffer_size >= 5) { + buffer[0] = 0x1A + offset; + +#ifdef IS_BIG_ENDIAN + memcpy(buffer + 1, &value, 4); +#else + buffer[1] = (unsigned char)(value >> 24); + buffer[2] = (unsigned char)(value >> 16); + buffer[3] = (unsigned char)(value >> 8); + buffer[4] = (unsigned char)value; +#endif + + return 5; + } else + return 0; +} + +size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset) { + if (buffer_size >= 9) { + buffer[0] = 0x1B + offset; + +#ifdef IS_BIG_ENDIAN + memcpy(buffer + 1, &value, 8); +#else + buffer[1] = (unsigned char)(value >> 56); + buffer[2] = (unsigned char)(value >> 48); + buffer[3] = (unsigned char)(value >> 40); + buffer[4] = (unsigned char)(value >> 32); + buffer[5] = (unsigned char)(value >> 24); + buffer[6] = (unsigned char)(value >> 16); + buffer[7] = (unsigned char)(value >> 8); + buffer[8] = (unsigned char)value; +#endif + + return 9; + } else + return 0; +} + +size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset) { + if (value <= UINT16_MAX) + if (value <= UINT8_MAX) + return _cbor_encode_uint8((uint8_t)value, buffer, buffer_size, offset); + else + return _cbor_encode_uint16((uint16_t)value, buffer, buffer_size, offset); + else if (value <= UINT32_MAX) + return _cbor_encode_uint32((uint32_t)value, buffer, buffer_size, offset); + else + return _cbor_encode_uint64((uint64_t)value, buffer, buffer_size, offset); +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.h new file mode 100644 index 00000000000..7eadb712164 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/encoders.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_ENCODERS_H +#define LIBCBOR_ENCODERS_H + +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +_CBOR_NODISCARD +size_t _cbor_encode_uint8(uint8_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset); + +_CBOR_NODISCARD +size_t _cbor_encode_uint16(uint16_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset); + +_CBOR_NODISCARD +size_t _cbor_encode_uint32(uint32_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset); + +_CBOR_NODISCARD +size_t _cbor_encode_uint64(uint64_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset); + +_CBOR_NODISCARD +size_t _cbor_encode_uint(uint64_t value, unsigned char *buffer, + size_t buffer_size, uint8_t offset); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_ENCODERS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.c new file mode 100644 index 00000000000..cfa173de790 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "loaders.h" +#include <math.h> +#include <string.h> + +uint8_t _cbor_load_uint8(cbor_data source) { return (uint8_t)*source; } + +uint16_t _cbor_load_uint16(const unsigned char *source) { +#ifdef IS_BIG_ENDIAN + uint16_t result; + memcpy(&result, source, 2); + return result; +#else + return ((uint16_t) * (source + 0) << 8) + (uint8_t) * (source + 1); +#endif +} + +uint32_t _cbor_load_uint32(const unsigned char *source) { +#ifdef IS_BIG_ENDIAN + uint32_t result; + memcpy(&result, source, 4); + return result; +#else + return ((uint32_t) * (source + 0) << 0x18) + + ((uint32_t) * (source + 1) << 0x10) + + ((uint16_t) * (source + 2) << 0x08) + (uint8_t) * (source + 3); +#endif +} + +uint64_t _cbor_load_uint64(const unsigned char *source) { +#ifdef IS_BIG_ENDIAN + uint64_t result; + memcpy(&result, source, 8); + return result; +#else + return ((uint64_t) * (source + 0) << 0x38) + + ((uint64_t) * (source + 1) << 0x30) + + ((uint64_t) * (source + 2) << 0x28) + + ((uint64_t) * (source + 3) << 0x20) + + ((uint32_t) * (source + 4) << 0x18) + + ((uint32_t) * (source + 5) << 0x10) + + ((uint16_t) * (source + 6) << 0x08) + (uint8_t) * (source + 7); +#endif +} + +/* As per https://www.rfc-editor.org/rfc/rfc8949.html#name-half-precision */ +float _cbor_decode_half(unsigned char *halfp) { + int half = (halfp[0] << 8) + halfp[1]; + int exp = (half >> 10) & 0x1f; + int mant = half & 0x3ff; + double val; + if (exp == 0) + val = ldexp(mant, -24); + else if (exp != 31) + val = ldexp(mant + 1024, exp - 25); + else + val = mant == 0 ? INFINITY : NAN; + return (float)(half & 0x8000 ? -val : val); +} + +float _cbor_load_half(cbor_data source) { + /* Discard const */ + return _cbor_decode_half((unsigned char *)source); +} + +float _cbor_load_float(cbor_data source) { + union _cbor_float_helper helper = {.as_uint = _cbor_load_uint32(source)}; + return helper.as_float; +} + +double _cbor_load_double(cbor_data source) { + union _cbor_double_helper helper = {.as_uint = _cbor_load_uint64(source)}; + return helper.as_double; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.h new file mode 100644 index 00000000000..ce37563a3d8 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/loaders.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_LOADERS_H +#define LIBCBOR_LOADERS_H + +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Read the given uint from the given location, no questions asked */ +_CBOR_NODISCARD +uint8_t _cbor_load_uint8(const unsigned char *source); + +_CBOR_NODISCARD +uint16_t _cbor_load_uint16(const unsigned char *source); + +_CBOR_NODISCARD +uint32_t _cbor_load_uint32(const unsigned char *source); + +_CBOR_NODISCARD +uint64_t _cbor_load_uint64(const unsigned char *source); + +_CBOR_NODISCARD +float _cbor_load_half(cbor_data source); + +_CBOR_NODISCARD +float _cbor_load_float(cbor_data source); + +_CBOR_NODISCARD +double _cbor_load_double(cbor_data source); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_LOADERS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.c new file mode 100644 index 00000000000..bbea63cb9f0 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "memory_utils.h" +#include "cbor/common.h" + +// TODO: Consider builtins +// (https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html) + +/** Highest on bit position */ +size_t _cbor_highest_bit(size_t number) { + size_t bit = 0; + while (number != 0) { + bit++; + number >>= 1; + } + + return bit; +} + +bool _cbor_safe_to_multiply(size_t a, size_t b) { + if (a <= 1 || b <= 1) return true; + return _cbor_highest_bit(a) + _cbor_highest_bit(b) <= sizeof(size_t) * 8; +} + +bool _cbor_safe_to_add(size_t a, size_t b) { + // Unsigned integer overflow doesn't constitute UB + size_t sum = a + b; + return sum >= a && sum >= b; +} + +size_t _cbor_safe_signaling_add(size_t a, size_t b) { + if (a == 0 || b == 0) return 0; + if (_cbor_safe_to_add(a, b)) return a + b; + return 0; +} + +void* _cbor_alloc_multiple(size_t item_size, size_t item_count) { + if (_cbor_safe_to_multiply(item_size, item_count)) { + return _cbor_malloc(item_size * item_count); + } else { + return NULL; + } +} + +void* _cbor_realloc_multiple(void* pointer, size_t item_size, + size_t item_count) { + if (_cbor_safe_to_multiply(item_size, item_count)) { + return _cbor_realloc(pointer, item_size * item_count); + } else { + return NULL; + } +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.h new file mode 100644 index 00000000000..696f67800e2 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/memory_utils.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_MEMORY_UTILS_H +#define LIBCBOR_MEMORY_UTILS_H + +#include <stdbool.h> +#include <string.h> + +#include "cbor/common.h" + +/** Can `a` and `b` be multiplied without overflowing size_t? */ +_CBOR_NODISCARD +bool _cbor_safe_to_multiply(size_t a, size_t b); + +/** Can `a` and `b` be added without overflowing size_t? */ +_CBOR_NODISCARD +bool _cbor_safe_to_add(size_t a, size_t b); + +/** Adds `a` and `b`, propagating zeros and returning 0 on overflow. */ +_CBOR_NODISCARD +size_t _cbor_safe_signaling_add(size_t a, size_t b); + +/** Overflow-proof contiguous array allocation + * + * @param item_size + * @param item_count + * @return Region of item_size * item_count bytes, or NULL if the total size + * overflows size_t or the underlying allocator failed + */ +void* _cbor_alloc_multiple(size_t item_size, size_t item_count); + +/** Overflow-proof contiguous array reallocation + * + * This implements the OpenBSD `reallocarray` functionality. + * + * @param pointer + * @param item_size + * @param item_count + * @return Realloc'd of item_size * item_count bytes, or NULL if the total size + * overflows size_t or the underlying allocator failed + */ +void* _cbor_realloc_multiple(void* pointer, size_t item_size, + size_t item_count); + +#endif // LIBCBOR_MEMORY_UTILS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.c new file mode 100644 index 00000000000..2db03cbbf08 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "stack.h" + +struct _cbor_stack _cbor_stack_init(void) { + return (struct _cbor_stack){.top = NULL, .size = 0}; +} + +void _cbor_stack_pop(struct _cbor_stack *stack) { + struct _cbor_stack_record *top = stack->top; + stack->top = stack->top->lower; + _cbor_free(top); + stack->size--; +} + +struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *stack, + cbor_item_t *item, + size_t subitems) { + if (stack->size == CBOR_MAX_STACK_SIZE) return NULL; + struct _cbor_stack_record *new_top = + _cbor_malloc(sizeof(struct _cbor_stack_record)); + if (new_top == NULL) return NULL; + + *new_top = (struct _cbor_stack_record){stack->top, item, subitems}; + stack->top = new_top; + stack->size++; + return new_top; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.h new file mode 100644 index 00000000000..cf2206b40e5 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/stack.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_STACK_H +#define LIBCBOR_STACK_H + +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Simple stack record for the parser */ +struct _cbor_stack_record { + /** Pointer to the parent stack frame */ + struct _cbor_stack_record *lower; + /** Item under construction */ + cbor_item_t *item; + /** + * How many outstanding subitems are expected. + * + * For example, when we see a new definite array, `subitems` is initialized to + * the array length. With every item added, the counter is decreased. When it + * reaches zero, the stack is popped and the complete item is propagated + * upwards. + */ + size_t subitems; +}; + +/** Stack handle - contents and size */ +struct _cbor_stack { + struct _cbor_stack_record *top; + size_t size; +}; + +_CBOR_NODISCARD +struct _cbor_stack _cbor_stack_init(void); + +void _cbor_stack_pop(struct _cbor_stack *); + +_CBOR_NODISCARD +struct _cbor_stack_record *_cbor_stack_push(struct _cbor_stack *, cbor_item_t *, + size_t); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_STACK_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.c new file mode 100644 index 00000000000..f87b746a3e1 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "unicode.h" +#include <stdint.h> + +#define UTF8_ACCEPT 0 +#define UTF8_REJECT 1 + +static const uint8_t utf8d[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00..1f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20..3f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40..5f */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60..7f */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, /* 80..9f */ + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* a0..bf */ + 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c0..df */ + 0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x4, 0x3, 0x3, /* e0..ef */ + 0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, + 0x8, 0x8, 0x8, 0x8, 0x8, /* f0..ff */ + 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, + 0x6, 0x1, 0x1, 0x1, 0x1, /* s0..s0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, /* s1..s2 */ + 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, /* s3..s4 */ + 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, /* s5..s6 */ + 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s7..s8 */ +}; + +/* Copyright of this function: (c) 2008-2009 Bjoern Hoehrmann + * <[email protected]> */ +/* See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. */ +uint32_t _cbor_unicode_decode(uint32_t* state, uint32_t* codep, uint32_t byte) { + uint32_t type = utf8d[byte]; + + *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) + : (0xff >> type) & (byte); + + *state = utf8d[256 + *state * 16 + type]; + return *state; +} + +size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, + struct _cbor_unicode_status* status) { + *status = + (struct _cbor_unicode_status){.location = 0, .status = _CBOR_UNICODE_OK}; + uint32_t codepoint, state = UTF8_ACCEPT, res; + size_t pos = 0, count = 0; + + for (; pos < source_length; pos++) { + res = _cbor_unicode_decode(&state, &codepoint, source[pos]); + + if (res == UTF8_ACCEPT) { + count++; + } else if (res == UTF8_REJECT) { + goto error; + } + } + + /* Unfinished multibyte codepoint */ + if (state != UTF8_ACCEPT) goto error; + + return count; + +error: + *status = (struct _cbor_unicode_status){.location = pos, + .status = _CBOR_UNICODE_BADCP}; + return 0; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.h new file mode 100644 index 00000000000..81d03d00778 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/internal/unicode.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_UNICODE_H +#define LIBCBOR_UNICODE_H + +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum _cbor_unicode_status_error { _CBOR_UNICODE_OK, _CBOR_UNICODE_BADCP }; + +/** Signals unicode validation error and possibly its location */ +struct _cbor_unicode_status { + enum _cbor_unicode_status_error status; + size_t location; +}; + +_CBOR_NODISCARD +size_t _cbor_unicode_codepoint_count(cbor_data source, size_t source_length, + struct _cbor_unicode_status* status); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_UNICODE_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.c new file mode 100644 index 00000000000..b4d035a1897 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "ints.h" + +cbor_int_width cbor_int_get_width(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + return item->metadata.int_metadata.width; +} + +uint8_t cbor_get_uint8(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_8); + return *item->data; +} + +uint16_t cbor_get_uint16(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_16); + return *(uint16_t *)item->data; +} + +uint32_t cbor_get_uint32(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_32); + return *(uint32_t *)item->data; +} + +uint64_t cbor_get_uint64(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_64); + return *(uint64_t *)item->data; +} + +uint64_t cbor_get_int(const cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + // cppcheck-suppress missingReturn + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + return cbor_get_uint8(item); + case CBOR_INT_16: + return cbor_get_uint16(item); + case CBOR_INT_32: + return cbor_get_uint32(item); + case CBOR_INT_64: + return cbor_get_uint64(item); + } +} + +void cbor_set_uint8(cbor_item_t *item, uint8_t value) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_8); + *item->data = value; +} + +void cbor_set_uint16(cbor_item_t *item, uint16_t value) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_16); + *(uint16_t *)item->data = value; +} + +void cbor_set_uint32(cbor_item_t *item, uint32_t value) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_32); + *(uint32_t *)item->data = value; +} + +void cbor_set_uint64(cbor_item_t *item, uint64_t value) { + CBOR_ASSERT(cbor_is_int(item)); + CBOR_ASSERT(cbor_int_get_width(item) == CBOR_INT_64); + *(uint64_t *)item->data = value; +} + +void cbor_mark_uint(cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + item->type = CBOR_TYPE_UINT; +} + +void cbor_mark_negint(cbor_item_t *item) { + CBOR_ASSERT(cbor_is_int(item)); + item->type = CBOR_TYPE_NEGINT; +} + +cbor_item_t *cbor_new_int8(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 1); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.int_metadata = {.width = CBOR_INT_8}}, + .type = CBOR_TYPE_UINT}; + return item; +} + +cbor_item_t *cbor_new_int16(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 2); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.int_metadata = {.width = CBOR_INT_16}}, + .type = CBOR_TYPE_UINT}; + return item; +} + +cbor_item_t *cbor_new_int32(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 4); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.int_metadata = {.width = CBOR_INT_32}}, + .type = CBOR_TYPE_UINT}; + return item; +} + +cbor_item_t *cbor_new_int64(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t) + 8); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){.data = (unsigned char *)item + sizeof(cbor_item_t), + .refcount = 1, + .metadata = {.int_metadata = {.width = CBOR_INT_64}}, + .type = CBOR_TYPE_UINT}; + return item; +} + +cbor_item_t *cbor_build_uint8(uint8_t value) { + cbor_item_t *item = cbor_new_int8(); + _CBOR_NOTNULL(item); + cbor_set_uint8(item, value); + cbor_mark_uint(item); + return item; +} + +cbor_item_t *cbor_build_uint16(uint16_t value) { + cbor_item_t *item = cbor_new_int16(); + _CBOR_NOTNULL(item); + cbor_set_uint16(item, value); + cbor_mark_uint(item); + return item; +} + +cbor_item_t *cbor_build_uint32(uint32_t value) { + cbor_item_t *item = cbor_new_int32(); + _CBOR_NOTNULL(item); + cbor_set_uint32(item, value); + cbor_mark_uint(item); + return item; +} + +cbor_item_t *cbor_build_uint64(uint64_t value) { + cbor_item_t *item = cbor_new_int64(); + _CBOR_NOTNULL(item); + cbor_set_uint64(item, value); + cbor_mark_uint(item); + return item; +} + +cbor_item_t *cbor_build_negint8(uint8_t value) { + cbor_item_t *item = cbor_new_int8(); + _CBOR_NOTNULL(item); + cbor_set_uint8(item, value); + cbor_mark_negint(item); + return item; +} + +cbor_item_t *cbor_build_negint16(uint16_t value) { + cbor_item_t *item = cbor_new_int16(); + _CBOR_NOTNULL(item); + cbor_set_uint16(item, value); + cbor_mark_negint(item); + return item; +} + +cbor_item_t *cbor_build_negint32(uint32_t value) { + cbor_item_t *item = cbor_new_int32(); + _CBOR_NOTNULL(item); + cbor_set_uint32(item, value); + cbor_mark_negint(item); + return item; +} + +cbor_item_t *cbor_build_negint64(uint64_t value) { + cbor_item_t *item = cbor_new_int64(); + _CBOR_NOTNULL(item); + cbor_set_uint64(item, value); + cbor_mark_negint(item); + return item; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.h new file mode 100644 index 00000000000..006aa428e0a --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/ints.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_INTS_H +#define LIBCBOR_INTS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * Integer (uints and negints) manipulation + * ============================================================================ + */ + +/** Extracts the integer value + * + * @param item positive or negative integer + * @return the value + */ +_CBOR_NODISCARD CBOR_EXPORT uint8_t cbor_get_uint8(const cbor_item_t *item); + +/** Extracts the integer value + * + * @param item positive or negative integer + * @return the value + */ +_CBOR_NODISCARD CBOR_EXPORT uint16_t cbor_get_uint16(const cbor_item_t *item); + +/** Extracts the integer value + * + * @param item positive or negative integer + * @return the value + */ +_CBOR_NODISCARD CBOR_EXPORT uint32_t cbor_get_uint32(const cbor_item_t *item); + +/** Extracts the integer value + * + * @param item positive or negative integer + * @return the value + */ +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_get_uint64(const cbor_item_t *item); + +/** Extracts the integer value + * + * @param item positive or negative integer + * @return the value, extended to `uint64_t` + */ +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_get_int(const cbor_item_t *item); + +/** Assigns the integer value + * + * @param item positive or negative integer item + * @param value the value to assign. For negative integer, the logical value is + * `-value - 1` + */ +CBOR_EXPORT void cbor_set_uint8(cbor_item_t *item, uint8_t value); + +/** Assigns the integer value + * + * @param item positive or negative integer item + * @param value the value to assign. For negative integer, the logical value is + * `-value - 1` + */ +CBOR_EXPORT void cbor_set_uint16(cbor_item_t *item, uint16_t value); + +/** Assigns the integer value + * + * @param item positive or negative integer item + * @param value the value to assign. For negative integer, the logical value is + * `-value - 1` + */ +CBOR_EXPORT void cbor_set_uint32(cbor_item_t *item, uint32_t value); + +/** Assigns the integer value + * + * @param item positive or negative integer item + * @param value the value to assign. For negative integer, the logical value is + * `-value - 1` + */ +CBOR_EXPORT void cbor_set_uint64(cbor_item_t *item, uint64_t value); + +/** Queries the integer width + * + * @param item positive or negative integer item + * @return the width + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_int_width +cbor_int_get_width(const cbor_item_t *item); + +/** Marks the integer item as a positive integer + * + * The data value is not changed + * + * @param item positive or negative integer item + */ +CBOR_EXPORT void cbor_mark_uint(cbor_item_t *item); + +/** Marks the integer item as a negative integer + * + * The data value is not changed + * + * @param item positive or negative integer item + */ +CBOR_EXPORT void cbor_mark_negint(cbor_item_t *item); + +/** Allocates new integer with 1B width + * + * The width cannot be changed once allocated + * + * @return **new** positive integer or `NULL` on memory allocation failure. The + * value is not initialized + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int8(void); + +/** Allocates new integer with 2B width + * + * The width cannot be changed once allocated + * + * @return **new** positive integer or `NULL` on memory allocation failure. The + * value is not initialized + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int16(void); + +/** Allocates new integer with 4B width + * + * The width cannot be changed once allocated + * + * @return **new** positive integer or `NULL` on memory allocation failure. The + * value is not initialized + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int32(void); + +/** Allocates new integer with 8B width + * + * The width cannot be changed once allocated + * + * @return **new** positive integer or `NULL` on memory allocation failure. The + * value is not initialized + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_int64(void); + +/** Constructs a new positive integer + * + * @param value the value to use + * @return **new** positive integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint8(uint8_t value); + +/** Constructs a new positive integer + * + * @param value the value to use + * @return **new** positive integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint16(uint16_t value); + +/** Constructs a new positive integer + * + * @param value the value to use + * @return **new** positive integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint32(uint32_t value); + +/** Constructs a new positive integer + * + * @param value the value to use + * @return **new** positive integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_uint64(uint64_t value); + +/** Constructs a new negative integer + * + * @param value the value to use + * @return **new** negative integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint8(uint8_t value); + +/** Constructs a new negative integer + * + * @param value the value to use + * @return **new** negative integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint16(uint16_t value); + +/** Constructs a new negative integer + * + * @param value the value to use + * @return **new** negative integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint32(uint32_t value); + +/** Constructs a new negative integer + * + * @param value the value to use + * @return **new** negative integer or `NULL` on memory allocation failure + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_negint64(uint64_t value); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_INTS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.c new file mode 100644 index 00000000000..8a3bd607568 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "maps.h" +#include "internal/memory_utils.h" + +size_t cbor_map_size(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_map(item)); + return item->metadata.map_metadata.end_ptr; +} + +size_t cbor_map_allocated(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_map(item)); + return item->metadata.map_metadata.allocated; +} + +cbor_item_t *cbor_new_definite_map(size_t size) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_MAP, + .metadata = {.map_metadata = {.allocated = size, + .type = _CBOR_METADATA_DEFINITE, + .end_ptr = 0}}, + .data = _cbor_alloc_multiple(sizeof(struct cbor_pair), size)}; + _CBOR_DEPENDENT_NOTNULL(item, item->data); + + return item; +} + +cbor_item_t *cbor_new_indefinite_map(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_MAP, + .metadata = {.map_metadata = {.allocated = 0, + .type = _CBOR_METADATA_INDEFINITE, + .end_ptr = 0}}, + .data = NULL}; + + return item; +} + +bool _cbor_map_add_key(cbor_item_t *item, cbor_item_t *key) { + CBOR_ASSERT(cbor_isa_map(item)); + struct _cbor_map_metadata *metadata = + (struct _cbor_map_metadata *)&item->metadata; + if (cbor_map_is_definite(item)) { + struct cbor_pair *data = cbor_map_handle(item); + if (metadata->end_ptr >= metadata->allocated) { + /* Don't realloc definite preallocated map */ + return false; + } + + data[metadata->end_ptr].key = key; + data[metadata->end_ptr++].value = NULL; + } else { + if (metadata->end_ptr >= metadata->allocated) { + /* Exponential realloc */ + // Check for overflows first + if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, metadata->allocated)) { + return false; + } + + size_t new_allocation = metadata->allocated == 0 + ? 1 + : CBOR_BUFFER_GROWTH * metadata->allocated; + + unsigned char *new_data = _cbor_realloc_multiple( + item->data, sizeof(struct cbor_pair), new_allocation); + + if (new_data == NULL) { + return false; + } + + item->data = new_data; + metadata->allocated = new_allocation; + } + struct cbor_pair *data = cbor_map_handle(item); + data[metadata->end_ptr].key = key; + data[metadata->end_ptr++].value = NULL; + } + cbor_incref(key); + return true; +} + +bool _cbor_map_add_value(cbor_item_t *item, cbor_item_t *value) { + CBOR_ASSERT(cbor_isa_map(item)); + cbor_incref(value); + cbor_map_handle(item)[ + /* Move one back since we are assuming _add_key (which increased the ptr) + * was the previous operation on this object */ + item->metadata.map_metadata.end_ptr - 1] + .value = value; + return true; +} + +// TODO: Add a more convenient API like add(item, key, val) +bool cbor_map_add(cbor_item_t *item, struct cbor_pair pair) { + CBOR_ASSERT(cbor_isa_map(item)); + if (!_cbor_map_add_key(item, pair.key)) return false; + return _cbor_map_add_value(item, pair.value); +} + +bool cbor_map_is_definite(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_map(item)); + return item->metadata.map_metadata.type == _CBOR_METADATA_DEFINITE; +} + +bool cbor_map_is_indefinite(const cbor_item_t *item) { + return !cbor_map_is_definite(item); +} + +struct cbor_pair *cbor_map_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_map(item)); + return (struct cbor_pair *)item->data; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.h new file mode 100644 index 00000000000..5c05b542bd8 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/maps.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_MAPS_H +#define LIBCBOR_MAPS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * Map manipulation + * ============================================================================ + */ + +/** Get the number of pairs + * + * @param item A map + * @return The number of pairs + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_map_size(const cbor_item_t *item); + +/** Get the size of the allocated storage + * + * @param item A map + * @return Allocated storage size (as the number of #cbor_pair items) + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_map_allocated(const cbor_item_t *item); + +/** Create a new definite map + * + * @param size The number of slots to preallocate + * @return Reference to the new map item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_definite_map(size_t size); + +/** Create a new indefinite map + * + * @return Reference to the new map item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_indefinite_map(void); + +/** Add a pair to the map + * + * For definite maps, items can only be added to the preallocated space. For + * indefinite maps, the storage will be expanded as needed + * + * @param item A map + * @param pair The key-value pair to add. Reference count of the #cbor_pair.key + * and #cbor_pair.value will be increased by one. + * @return `true` on success, `false` if memory allocation failed (indefinite + * maps) or the preallocated storage is full (definite maps) + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_add(cbor_item_t *item, + struct cbor_pair pair); + +/** Add a key to the map + * + * Sets the value to `NULL`. Internal API. + * + * @param item A map + * @param key The key, Its reference count will be be increased by one. + * @return `true` on success, `false` if either reallocation failed or the + * preallocated storage is full + */ +_CBOR_NODISCARD CBOR_EXPORT bool _cbor_map_add_key(cbor_item_t *item, + cbor_item_t *key); + +/** Add a value to the map + * + * Assumes that #_cbor_map_add_key has been called. Internal API. + * + * @param item A map + * @param value The value. Its reference count will be be increased by one. + * @return `true` on success, `false` if either reallocation failed or the + * preallocated storage is full + */ +_CBOR_NODISCARD CBOR_EXPORT bool _cbor_map_add_value(cbor_item_t *item, + cbor_item_t *value); + +/** Is this map definite? + * + * @param item A map + * @return Is this map definite? + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_is_definite(const cbor_item_t *item); + +/** Is this map indefinite? + * + * @param item A map + * @return Is this map indefinite? + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_map_is_indefinite( + const cbor_item_t *item); + +/** Get the pairs storage + * + * @param item A map + * @return Array of #cbor_map_size pairs. Manipulation is possible as long as + * references remain valid. + */ +_CBOR_NODISCARD CBOR_EXPORT struct cbor_pair *cbor_map_handle( + const cbor_item_t *item); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_MAPS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.c new file mode 100644 index 00000000000..40f4c531d57 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "serialization.h" +#include <string.h> +#include "cbor/arrays.h" +#include "cbor/bytestrings.h" +#include "cbor/floats_ctrls.h" +#include "cbor/ints.h" +#include "cbor/maps.h" +#include "cbor/strings.h" +#include "cbor/tags.h" +#include "encoding.h" +#include "internal/memory_utils.h" + +size_t cbor_serialize(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + // cppcheck-suppress missingReturn + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: + return cbor_serialize_uint(item, buffer, buffer_size); + case CBOR_TYPE_NEGINT: + return cbor_serialize_negint(item, buffer, buffer_size); + case CBOR_TYPE_BYTESTRING: + return cbor_serialize_bytestring(item, buffer, buffer_size); + case CBOR_TYPE_STRING: + return cbor_serialize_string(item, buffer, buffer_size); + case CBOR_TYPE_ARRAY: + return cbor_serialize_array(item, buffer, buffer_size); + case CBOR_TYPE_MAP: + return cbor_serialize_map(item, buffer, buffer_size); + case CBOR_TYPE_TAG: + return cbor_serialize_tag(item, buffer, buffer_size); + case CBOR_TYPE_FLOAT_CTRL: + return cbor_serialize_float_ctrl(item, buffer, buffer_size); + } +} + +/** Largest integer that can be encoded as embedded in the item leading byte. */ +const uint64_t kMaxEmbeddedInt = 23; + +/** How many bytes will a tag for a nested item of a given `size` take when + * encoded.*/ +size_t _cbor_encoded_header_size(uint64_t size) { + if (size <= kMaxEmbeddedInt) + return 1; + else if (size <= UINT8_MAX) + return 2; + else if (size <= UINT16_MAX) + return 3; + else if (size <= UINT32_MAX) + return 5; + else + return 9; +} + +size_t cbor_serialized_size(const cbor_item_t *item) { + // cppcheck-suppress missingReturn + switch (cbor_typeof(item)) { + case CBOR_TYPE_UINT: + case CBOR_TYPE_NEGINT: + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + if (cbor_get_uint8(item) <= kMaxEmbeddedInt) return 1; + return 2; + case CBOR_INT_16: + return 3; + case CBOR_INT_32: + return 5; + case CBOR_INT_64: + return 9; + } + // Note: We do not _cbor_safe_signaling_add zero-length definite strings, + // they would cause zeroes to propagate. All other items are at least one + // byte. + case CBOR_TYPE_BYTESTRING: { + if (cbor_bytestring_is_definite(item)) { + size_t header_size = + _cbor_encoded_header_size(cbor_bytestring_length(item)); + if (cbor_bytestring_length(item) == 0) return header_size; + return _cbor_safe_signaling_add(header_size, + cbor_bytestring_length(item)); + } + size_t indef_bytestring_size = 2; // Leading byte + break + cbor_item_t **chunks = cbor_bytestring_chunks_handle(item); + for (size_t i = 0; i < cbor_bytestring_chunk_count(item); i++) { + indef_bytestring_size = _cbor_safe_signaling_add( + indef_bytestring_size, cbor_serialized_size(chunks[i])); + } + return indef_bytestring_size; + } + case CBOR_TYPE_STRING: { + if (cbor_string_is_definite(item)) { + size_t header_size = + _cbor_encoded_header_size(cbor_string_length(item)); + if (cbor_string_length(item) == 0) return header_size; + return _cbor_safe_signaling_add(header_size, cbor_string_length(item)); + } + size_t indef_string_size = 2; // Leading byte + break + cbor_item_t **chunks = cbor_string_chunks_handle(item); + for (size_t i = 0; i < cbor_string_chunk_count(item); i++) { + indef_string_size = _cbor_safe_signaling_add( + indef_string_size, cbor_serialized_size(chunks[i])); + } + return indef_string_size; + } + case CBOR_TYPE_ARRAY: { + size_t array_size = cbor_array_is_definite(item) + ? _cbor_encoded_header_size(cbor_array_size(item)) + : 2; // Leading byte + break + cbor_item_t **items = cbor_array_handle(item); + for (size_t i = 0; i < cbor_array_size(item); i++) { + array_size = _cbor_safe_signaling_add(array_size, + cbor_serialized_size(items[i])); + } + return array_size; + } + case CBOR_TYPE_MAP: { + size_t map_size = cbor_map_is_definite(item) + ? _cbor_encoded_header_size(cbor_map_size(item)) + : 2; // Leading byte + break + struct cbor_pair *items = cbor_map_handle(item); + for (size_t i = 0; i < cbor_map_size(item); i++) { + map_size = _cbor_safe_signaling_add( + map_size, + _cbor_safe_signaling_add(cbor_serialized_size(items[i].key), + cbor_serialized_size(items[i].value))); + } + return map_size; + } + case CBOR_TYPE_TAG: { + return _cbor_safe_signaling_add( + _cbor_encoded_header_size(cbor_tag_value(item)), + cbor_serialized_size(cbor_move(cbor_tag_item(item)))); + } + case CBOR_TYPE_FLOAT_CTRL: + switch (cbor_float_get_width(item)) { + case CBOR_FLOAT_0: + return _cbor_encoded_header_size(cbor_ctrl_value(item)); + case CBOR_FLOAT_16: + return 3; + case CBOR_FLOAT_32: + return 5; + case CBOR_FLOAT_64: + return 9; + } + } +} + +size_t cbor_serialize_alloc(const cbor_item_t *item, unsigned char **buffer, + size_t *buffer_size) { + *buffer = NULL; + size_t serialized_size = cbor_serialized_size(item); + if (serialized_size == 0) { + if (buffer_size != NULL) *buffer_size = 0; + return 0; + } + *buffer = _cbor_malloc(serialized_size); + if (*buffer == NULL) { + if (buffer_size != NULL) *buffer_size = 0; + return 0; + } + + size_t written = cbor_serialize(item, *buffer, serialized_size); + CBOR_ASSERT(written == serialized_size); + if (buffer_size != NULL) *buffer_size = serialized_size; + return written; +} + +size_t cbor_serialize_uint(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_uint(item)); + // cppcheck-suppress missingReturn + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + return cbor_encode_uint8(cbor_get_uint8(item), buffer, buffer_size); + case CBOR_INT_16: + return cbor_encode_uint16(cbor_get_uint16(item), buffer, buffer_size); + case CBOR_INT_32: + return cbor_encode_uint32(cbor_get_uint32(item), buffer, buffer_size); + case CBOR_INT_64: + return cbor_encode_uint64(cbor_get_uint64(item), buffer, buffer_size); + } +} + +size_t cbor_serialize_negint(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_negint(item)); + // cppcheck-suppress missingReturn + switch (cbor_int_get_width(item)) { + case CBOR_INT_8: + return cbor_encode_negint8(cbor_get_uint8(item), buffer, buffer_size); + case CBOR_INT_16: + return cbor_encode_negint16(cbor_get_uint16(item), buffer, buffer_size); + case CBOR_INT_32: + return cbor_encode_negint32(cbor_get_uint32(item), buffer, buffer_size); + case CBOR_INT_64: + return cbor_encode_negint64(cbor_get_uint64(item), buffer, buffer_size); + } +} + +size_t cbor_serialize_bytestring(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_bytestring(item)); + if (cbor_bytestring_is_definite(item)) { + size_t length = cbor_bytestring_length(item); + size_t written = cbor_encode_bytestring_start(length, buffer, buffer_size); + if (written > 0 && (buffer_size - written >= length)) { + memcpy(buffer + written, cbor_bytestring_handle(item), length); + return written + length; + } + return 0; + } else { + CBOR_ASSERT(cbor_bytestring_is_indefinite(item)); + size_t chunk_count = cbor_bytestring_chunk_count(item); + size_t written = cbor_encode_indef_bytestring_start(buffer, buffer_size); + if (written == 0) return 0; + + cbor_item_t **chunks = cbor_bytestring_chunks_handle(item); + for (size_t i = 0; i < chunk_count; i++) { + size_t chunk_written = cbor_serialize_bytestring( + chunks[i], buffer + written, buffer_size - written); + if (chunk_written == 0) return 0; + written += chunk_written; + } + + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; + } +} + +size_t cbor_serialize_string(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_string(item)); + if (cbor_string_is_definite(item)) { + size_t length = cbor_string_length(item); + size_t written = cbor_encode_string_start(length, buffer, buffer_size); + if (written && (buffer_size - written >= length)) { + memcpy(buffer + written, cbor_string_handle(item), length); + return written + length; + } + return 0; + } else { + CBOR_ASSERT(cbor_string_is_indefinite(item)); + size_t chunk_count = cbor_string_chunk_count(item); + size_t written = cbor_encode_indef_string_start(buffer, buffer_size); + if (written == 0) return 0; + + cbor_item_t **chunks = cbor_string_chunks_handle(item); + for (size_t i = 0; i < chunk_count; i++) { + size_t chunk_written = cbor_serialize_string(chunks[i], buffer + written, + buffer_size - written); + if (chunk_written == 0) return 0; + written += chunk_written; + } + + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; + } +} + +size_t cbor_serialize_array(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_array(item)); + size_t size = cbor_array_size(item), written = 0; + cbor_item_t **handle = cbor_array_handle(item); + if (cbor_array_is_definite(item)) { + written = cbor_encode_array_start(size, buffer, buffer_size); + } else { + CBOR_ASSERT(cbor_array_is_indefinite(item)); + written = cbor_encode_indef_array_start(buffer, buffer_size); + } + if (written == 0) return 0; + + for (size_t i = 0; i < size; i++) { + size_t item_written = + cbor_serialize(*(handle++), buffer + written, buffer_size - written); + if (item_written == 0) return 0; + written += item_written; + } + + if (cbor_array_is_definite(item)) { + return written; + } else { + CBOR_ASSERT(cbor_array_is_indefinite(item)); + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; + } +} + +size_t cbor_serialize_map(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_map(item)); + size_t size = cbor_map_size(item), written = 0; + struct cbor_pair *handle = cbor_map_handle(item); + + if (cbor_map_is_definite(item)) { + written = cbor_encode_map_start(size, buffer, buffer_size); + } else { + CBOR_ASSERT(cbor_map_is_indefinite(item)); + written = cbor_encode_indef_map_start(buffer, buffer_size); + } + if (written == 0) return 0; + + for (size_t i = 0; i < size; i++) { + size_t item_written = + cbor_serialize(handle->key, buffer + written, buffer_size - written); + if (item_written == 0) { + return 0; + } + written += item_written; + item_written = cbor_serialize((handle++)->value, buffer + written, + buffer_size - written); + if (item_written == 0) return 0; + written += item_written; + } + + if (cbor_map_is_definite(item)) { + return written; + } else { + CBOR_ASSERT(cbor_map_is_indefinite(item)); + size_t break_written = + cbor_encode_break(buffer + written, buffer_size - written); + if (break_written == 0) return 0; + return written + break_written; + } +} + +size_t cbor_serialize_tag(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_tag(item)); + size_t written = cbor_encode_tag(cbor_tag_value(item), buffer, buffer_size); + if (written == 0) return 0; + + size_t item_written = cbor_serialize(cbor_move(cbor_tag_item(item)), + buffer + written, buffer_size - written); + if (item_written == 0) return 0; + return written + item_written; +} + +size_t cbor_serialize_float_ctrl(const cbor_item_t *item, unsigned char *buffer, + size_t buffer_size) { + CBOR_ASSERT(cbor_isa_float_ctrl(item)); + // cppcheck-suppress missingReturn + switch (cbor_float_get_width(item)) { + case CBOR_FLOAT_0: + /* CTRL - special treatment */ + return cbor_encode_ctrl(cbor_ctrl_value(item), buffer, buffer_size); + case CBOR_FLOAT_16: + return cbor_encode_half(cbor_float_get_float2(item), buffer, buffer_size); + case CBOR_FLOAT_32: + return cbor_encode_single(cbor_float_get_float4(item), buffer, + buffer_size); + case CBOR_FLOAT_64: + return cbor_encode_double(cbor_float_get_float8(item), buffer, + buffer_size); + } +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.h new file mode 100644 index 00000000000..228ae75d601 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/serialization.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_SERIALIZATION_H +#define LIBCBOR_SERIALIZATION_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * High level encoding + * ============================================================================ + */ + +/** Serialize the given item + * + * @param item A data item + * @param buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result. 0 on failure. + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize(const cbor_item_t *item, + cbor_mutable_data buffer, + size_t buffer_size); + +/** Compute the length (in bytes) of the item when serialized using + * `cbor_serialize`. + * + * Time complexity is proportional to the number of nested items. + * + * @param item A data item + * @return Length (>= 1) of the item when serialized. 0 if the length overflows + * `size_t`. + */ +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_serialized_size(const cbor_item_t *item); + +/** Serialize the given item, allocating buffers as needed + * + * Since libcbor v0.10, the return value is always the same as `buffer_size` (if + * provided, see https://github.com/PJK/libcbor/pull/251/). New clients should + * ignore the return value. + * + * \rst + * .. warning:: It is the caller's responsibility to free the buffer using an + * appropriate ``free`` implementation. + * \endrst + * + * @param item A data item + * @param[out] buffer Buffer containing the result + * @param[out] buffer_size Size of the \p buffer, or 0 on memory allocation + * failure. + * @return Length of the result in bytes + * @return 0 on memory allocation failure, in which case \p buffer is `NULL`. + */ +CBOR_EXPORT size_t cbor_serialize_alloc(const cbor_item_t *item, + unsigned char **buffer, + size_t *buffer_size); + +/** Serialize an uint + * + * @param item A uint + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_uint(const cbor_item_t *item, + cbor_mutable_data buffer, + size_t buffer_size); + +/** Serialize a negint + * + * @param item A negint + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_negint( + const cbor_item_t *item, cbor_mutable_data buffer, size_t buffer_size); + +/** Serialize a bytestring + * + * @param item A bytestring + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result. The \p buffer may + * still be modified + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_bytestring( + const cbor_item_t *item, cbor_mutable_data buffer, size_t buffer_size); + +/** Serialize a string + * + * @param item A string + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result. The \p buffer may + * still be modified + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_string( + const cbor_item_t *item, cbor_mutable_data buffer, size_t buffer_size); +/** Serialize an array + * + * @param item An array + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result. The \p buffer may + * still be modified + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_array( + const cbor_item_t *item, cbor_mutable_data buffer, size_t buffer_size); + +/** Serialize a map + * + * @param item A map + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result. The \p buffer may + * still be modified + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_map(const cbor_item_t *item, + cbor_mutable_data buffer, + size_t buffer_size); + +/** Serialize a tag + * + * @param item A tag + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result. The \p buffer may + * still be modified + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_tag(const cbor_item_t *item, + cbor_mutable_data buffer, + size_t buffer_size); + +/** Serialize a + * + * @param item A float or ctrl + * @param[out] buffer Buffer to serialize to + * @param buffer_size Size of the \p buffer + * @return Length of the result + * @return 0 if the \p buffer_size doesn't fit the result + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_serialize_float_ctrl( + const cbor_item_t *item, cbor_mutable_data buffer, size_t buffer_size); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_SERIALIZATION_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.c new file mode 100644 index 00000000000..4b37701143a --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "streaming.h" +#include "internal/loaders.h" + +static bool claim_bytes(size_t required, size_t provided, + struct cbor_decoder_result *result) { + if (required > (provided - result->read)) { + result->required = required + result->read; + result->read = 0; + result->status = CBOR_DECODER_NEDATA; + return false; + } else { + result->read += required; + result->required = 0; + return true; + } +} + +// Use implicit capture as an exception to avoid the super long parameter list +#define CLAIM_BYTES_AND_INVOKE(callback_name, length, source_extra_offset) \ + do { \ + if (claim_bytes(length, source_size, &result)) { \ + callbacks->callback_name(context, source + 1 + source_extra_offset, \ + length); \ + } \ + } while (0) + +#define READ_CLAIM_INVOKE(callback_name, length_reader, length_bytes) \ + do { \ + if (claim_bytes(length_bytes, source_size, &result)) { \ + uint64_t length = length_reader(source + 1); \ + CLAIM_BYTES_AND_INVOKE(callback_name, length, length_bytes); \ + } \ + return result; \ + } while (0) + +struct cbor_decoder_result cbor_stream_decode( + cbor_data source, size_t source_size, + const struct cbor_callbacks *callbacks, void *context) { + // Attempt to claim the initial MTB byte + struct cbor_decoder_result result = {.status = CBOR_DECODER_FINISHED}; + if (!claim_bytes(1, source_size, &result)) { + return result; + } + + switch (*source) { + case 0x00: /* Fallthrough */ + case 0x01: /* Fallthrough */ + case 0x02: /* Fallthrough */ + case 0x03: /* Fallthrough */ + case 0x04: /* Fallthrough */ + case 0x05: /* Fallthrough */ + case 0x06: /* Fallthrough */ + case 0x07: /* Fallthrough */ + case 0x08: /* Fallthrough */ + case 0x09: /* Fallthrough */ + case 0x0A: /* Fallthrough */ + case 0x0B: /* Fallthrough */ + case 0x0C: /* Fallthrough */ + case 0x0D: /* Fallthrough */ + case 0x0E: /* Fallthrough */ + case 0x0F: /* Fallthrough */ + case 0x10: /* Fallthrough */ + case 0x11: /* Fallthrough */ + case 0x12: /* Fallthrough */ + case 0x13: /* Fallthrough */ + case 0x14: /* Fallthrough */ + case 0x15: /* Fallthrough */ + case 0x16: /* Fallthrough */ + case 0x17: + /* Embedded one byte unsigned integer */ + { + callbacks->uint8(context, _cbor_load_uint8(source)); + return result; + } + case 0x18: + /* One byte unsigned integer */ + { + if (claim_bytes(1, source_size, &result)) { + callbacks->uint8(context, _cbor_load_uint8(source + 1)); + } + return result; + } + case 0x19: + /* Two bytes unsigned integer */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->uint16(context, _cbor_load_uint16(source + 1)); + } + return result; + } + case 0x1A: + /* Four bytes unsigned integer */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->uint32(context, _cbor_load_uint32(source + 1)); + } + return result; + } + case 0x1B: + /* Eight bytes unsigned integer */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->uint64(context, _cbor_load_uint64(source + 1)); + } + return result; + } + case 0x1C: /* Fallthrough */ + case 0x1D: /* Fallthrough */ + case 0x1E: /* Fallthrough */ + case 0x1F: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0x20: /* Fallthrough */ + case 0x21: /* Fallthrough */ + case 0x22: /* Fallthrough */ + case 0x23: /* Fallthrough */ + case 0x24: /* Fallthrough */ + case 0x25: /* Fallthrough */ + case 0x26: /* Fallthrough */ + case 0x27: /* Fallthrough */ + case 0x28: /* Fallthrough */ + case 0x29: /* Fallthrough */ + case 0x2A: /* Fallthrough */ + case 0x2B: /* Fallthrough */ + case 0x2C: /* Fallthrough */ + case 0x2D: /* Fallthrough */ + case 0x2E: /* Fallthrough */ + case 0x2F: /* Fallthrough */ + case 0x30: /* Fallthrough */ + case 0x31: /* Fallthrough */ + case 0x32: /* Fallthrough */ + case 0x33: /* Fallthrough */ + case 0x34: /* Fallthrough */ + case 0x35: /* Fallthrough */ + case 0x36: /* Fallthrough */ + case 0x37: + /* Embedded one byte negative integer */ + { + callbacks->negint8(context, + _cbor_load_uint8(source) - 0x20); /* 0x20 offset */ + return result; + } + case 0x38: + /* One byte negative integer */ + { + if (claim_bytes(1, source_size, &result)) { + callbacks->negint8(context, _cbor_load_uint8(source + 1)); + } + return result; + } + case 0x39: + /* Two bytes negative integer */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->negint16(context, _cbor_load_uint16(source + 1)); + } + return result; + } + case 0x3A: + /* Four bytes negative integer */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->negint32(context, _cbor_load_uint32(source + 1)); + } + return result; + } + case 0x3B: + /* Eight bytes negative integer */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->negint64(context, _cbor_load_uint64(source + 1)); + } + return result; + } + case 0x3C: /* Fallthrough */ + case 0x3D: /* Fallthrough */ + case 0x3E: /* Fallthrough */ + case 0x3F: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0x40: /* Fallthrough */ + case 0x41: /* Fallthrough */ + case 0x42: /* Fallthrough */ + case 0x43: /* Fallthrough */ + case 0x44: /* Fallthrough */ + case 0x45: /* Fallthrough */ + case 0x46: /* Fallthrough */ + case 0x47: /* Fallthrough */ + case 0x48: /* Fallthrough */ + case 0x49: /* Fallthrough */ + case 0x4A: /* Fallthrough */ + case 0x4B: /* Fallthrough */ + case 0x4C: /* Fallthrough */ + case 0x4D: /* Fallthrough */ + case 0x4E: /* Fallthrough */ + case 0x4F: /* Fallthrough */ + case 0x50: /* Fallthrough */ + case 0x51: /* Fallthrough */ + case 0x52: /* Fallthrough */ + case 0x53: /* Fallthrough */ + case 0x54: /* Fallthrough */ + case 0x55: /* Fallthrough */ + case 0x56: /* Fallthrough */ + case 0x57: + /* Embedded length byte string */ + { + uint64_t length = _cbor_load_uint8(source) - 0x40; /* 0x40 offset */ + CLAIM_BYTES_AND_INVOKE(byte_string, length, 0); + return result; + } + case 0x58: + /* One byte length byte string */ + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint8, 1); + case 0x59: + /* Two bytes length byte string */ + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint16, 2); + case 0x5A: + /* Four bytes length byte string */ + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint32, 4); + case 0x5B: + /* Eight bytes length byte string */ + READ_CLAIM_INVOKE(byte_string, _cbor_load_uint64, 8); + case 0x5C: /* Fallthrough */ + case 0x5D: /* Fallthrough */ + case 0x5E: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0x5F: + /* Indefinite byte string */ + { + callbacks->byte_string_start(context); + return result; + } + case 0x60: /* Fallthrough */ + case 0x61: /* Fallthrough */ + case 0x62: /* Fallthrough */ + case 0x63: /* Fallthrough */ + case 0x64: /* Fallthrough */ + case 0x65: /* Fallthrough */ + case 0x66: /* Fallthrough */ + case 0x67: /* Fallthrough */ + case 0x68: /* Fallthrough */ + case 0x69: /* Fallthrough */ + case 0x6A: /* Fallthrough */ + case 0x6B: /* Fallthrough */ + case 0x6C: /* Fallthrough */ + case 0x6D: /* Fallthrough */ + case 0x6E: /* Fallthrough */ + case 0x6F: /* Fallthrough */ + case 0x70: /* Fallthrough */ + case 0x71: /* Fallthrough */ + case 0x72: /* Fallthrough */ + case 0x73: /* Fallthrough */ + case 0x74: /* Fallthrough */ + case 0x75: /* Fallthrough */ + case 0x76: /* Fallthrough */ + case 0x77: + /* Embedded one byte length string */ + { + uint64_t length = _cbor_load_uint8(source) - 0x60; /* 0x60 offset */ + CLAIM_BYTES_AND_INVOKE(string, length, 0); + return result; + } + case 0x78: + /* One byte length string */ + READ_CLAIM_INVOKE(string, _cbor_load_uint8, 1); + case 0x79: + /* Two bytes length string */ + READ_CLAIM_INVOKE(string, _cbor_load_uint16, 2); + case 0x7A: + /* Four bytes length string */ + READ_CLAIM_INVOKE(string, _cbor_load_uint32, 4); + case 0x7B: + /* Eight bytes length string */ + READ_CLAIM_INVOKE(string, _cbor_load_uint64, 8); + case 0x7C: /* Fallthrough */ + case 0x7D: /* Fallthrough */ + case 0x7E: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0x7F: + /* Indefinite length string */ + { + callbacks->string_start(context); + return result; + } + case 0x80: /* Fallthrough */ + case 0x81: /* Fallthrough */ + case 0x82: /* Fallthrough */ + case 0x83: /* Fallthrough */ + case 0x84: /* Fallthrough */ + case 0x85: /* Fallthrough */ + case 0x86: /* Fallthrough */ + case 0x87: /* Fallthrough */ + case 0x88: /* Fallthrough */ + case 0x89: /* Fallthrough */ + case 0x8A: /* Fallthrough */ + case 0x8B: /* Fallthrough */ + case 0x8C: /* Fallthrough */ + case 0x8D: /* Fallthrough */ + case 0x8E: /* Fallthrough */ + case 0x8F: /* Fallthrough */ + case 0x90: /* Fallthrough */ + case 0x91: /* Fallthrough */ + case 0x92: /* Fallthrough */ + case 0x93: /* Fallthrough */ + case 0x94: /* Fallthrough */ + case 0x95: /* Fallthrough */ + case 0x96: /* Fallthrough */ + case 0x97: + /* Embedded one byte length array */ + { + callbacks->array_start( + context, _cbor_load_uint8(source) - 0x80); /* 0x40 offset */ + return result; + } + case 0x98: + /* One byte length array */ + { + if (claim_bytes(1, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint8(source + 1)); + } + return result; + } + case 0x99: + /* Two bytes length array */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint16(source + 1)); + } + return result; + } + case 0x9A: + /* Four bytes length array */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint32(source + 1)); + } + return result; + } + case 0x9B: + /* Eight bytes length array */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->array_start(context, _cbor_load_uint64(source + 1)); + } + return result; + } + case 0x9C: /* Fallthrough */ + case 0x9D: /* Fallthrough */ + case 0x9E: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0x9F: + /* Indefinite length array */ + { + callbacks->indef_array_start(context); + return result; + } + case 0xA0: /* Fallthrough */ + case 0xA1: /* Fallthrough */ + case 0xA2: /* Fallthrough */ + case 0xA3: /* Fallthrough */ + case 0xA4: /* Fallthrough */ + case 0xA5: /* Fallthrough */ + case 0xA6: /* Fallthrough */ + case 0xA7: /* Fallthrough */ + case 0xA8: /* Fallthrough */ + case 0xA9: /* Fallthrough */ + case 0xAA: /* Fallthrough */ + case 0xAB: /* Fallthrough */ + case 0xAC: /* Fallthrough */ + case 0xAD: /* Fallthrough */ + case 0xAE: /* Fallthrough */ + case 0xAF: /* Fallthrough */ + case 0xB0: /* Fallthrough */ + case 0xB1: /* Fallthrough */ + case 0xB2: /* Fallthrough */ + case 0xB3: /* Fallthrough */ + case 0xB4: /* Fallthrough */ + case 0xB5: /* Fallthrough */ + case 0xB6: /* Fallthrough */ + case 0xB7: + /* Embedded one byte length map */ + { + callbacks->map_start(context, + _cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */ + return result; + } + case 0xB8: + /* One byte length map */ + { + if (claim_bytes(1, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint8(source + 1)); + } + return result; + } + case 0xB9: + /* Two bytes length map */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint16(source + 1)); + } + return result; + } + case 0xBA: + /* Four bytes length map */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint32(source + 1)); + } + return result; + } + case 0xBB: + /* Eight bytes length map */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->map_start(context, _cbor_load_uint64(source + 1)); + } + return result; + } + case 0xBC: /* Fallthrough */ + case 0xBD: /* Fallthrough */ + case 0xBE: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0xBF: + /* Indefinite length map */ + { + callbacks->indef_map_start(context); + return result; + } + /* See https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml for tag + * assignment. All well-formed tags are processed regardless of validity + * since maintaining the known mapping would be impractical. + * + * Moreover, even tags in the reserved "standard" range are not assigned + * but may get assigned in the future (see e.g. + * https://github.com/PJK/libcbor/issues/307), so processing all tags + * improves forward compatibility. + */ + case 0xC0: /* Fallthrough */ + case 0xC1: /* Fallthrough */ + case 0xC2: /* Fallthrough */ + case 0xC3: /* Fallthrough */ + case 0xC4: /* Fallthrough */ + case 0xC5: /* Fallthrough */ + case 0xC6: /* Fallthrough */ + case 0xC7: /* Fallthrough */ + case 0xC8: /* Fallthrough */ + case 0xC9: /* Fallthrough */ + case 0xCA: /* Fallthrough */ + case 0xCB: /* Fallthrough */ + case 0xCC: /* Fallthrough */ + case 0xCD: /* Fallthrough */ + case 0xCE: /* Fallthrough */ + case 0xCF: /* Fallthrough */ + case 0xD0: /* Fallthrough */ + case 0xD1: /* Fallthrough */ + case 0xD2: /* Fallthrough */ + case 0xD3: /* Fallthrough */ + case 0xD4: /* Fallthrough */ + case 0xD5: /* Fallthrough */ + case 0xD6: /* Fallthrough */ + case 0xD7: /* Fallthrough */ + { + callbacks->tag(context, (uint64_t)(_cbor_load_uint8(source) - + 0xC0)); /* 0xC0 offset */ + return result; + } + case 0xD8: /* 1B tag */ + { + if (claim_bytes(1, source_size, &result)) { + callbacks->tag(context, _cbor_load_uint8(source + 1)); + } + return result; + } + case 0xD9: /* 2B tag */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->tag(context, _cbor_load_uint16(source + 1)); + } + return result; + } + case 0xDA: /* 4B tag */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->tag(context, _cbor_load_uint32(source + 1)); + } + return result; + } + case 0xDB: /* 8B tag */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->tag(context, _cbor_load_uint64(source + 1)); + } + return result; + } + case 0xDC: /* Fallthrough */ + case 0xDD: /* Fallthrough */ + case 0xDE: /* Fallthrough */ + case 0xDF: /* Reserved */ + { + return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; + } + case 0xE0: /* Fallthrough */ + case 0xE1: /* Fallthrough */ + case 0xE2: /* Fallthrough */ + case 0xE3: /* Fallthrough */ + case 0xE4: /* Fallthrough */ + case 0xE5: /* Fallthrough */ + case 0xE6: /* Fallthrough */ + case 0xE7: /* Fallthrough */ + case 0xE8: /* Fallthrough */ + case 0xE9: /* Fallthrough */ + case 0xEA: /* Fallthrough */ + case 0xEB: /* Fallthrough */ + case 0xEC: /* Fallthrough */ + case 0xED: /* Fallthrough */ + case 0xEE: /* Fallthrough */ + case 0xEF: /* Fallthrough */ + case 0xF0: /* Fallthrough */ + case 0xF1: /* Fallthrough */ + case 0xF2: /* Fallthrough */ + case 0xF3: /* Simple value - unassigned */ + { + return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; + } + case 0xF4: + /* False */ + { + callbacks->boolean(context, false); + return result; + } + case 0xF5: + /* True */ + { + callbacks->boolean(context, true); + return result; + } + case 0xF6: + /* Null */ + { + callbacks->null(context); + return result; + } + case 0xF7: + /* Undefined */ + { + callbacks->undefined(context); + return result; + } + case 0xF8: + /* 1B simple value, unassigned */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0xF9: + /* 2B float */ + { + if (claim_bytes(2, source_size, &result)) { + callbacks->float2(context, _cbor_load_half(source + 1)); + } + return result; + } + case 0xFA: + /* 4B float */ + { + if (claim_bytes(4, source_size, &result)) { + callbacks->float4(context, _cbor_load_float(source + 1)); + } + return result; + } + case 0xFB: + /* 8B float */ + { + if (claim_bytes(8, source_size, &result)) { + callbacks->float8(context, _cbor_load_double(source + 1)); + } + return result; + } + case 0xFC: /* Fallthrough */ + case 0xFD: /* Fallthrough */ + case 0xFE: + /* Reserved */ + { return (struct cbor_decoder_result){.status = CBOR_DECODER_ERROR}; } + case 0xFF: + /* Break */ + callbacks->indef_break(context); + // Never happens, the switch statement is exhaustive on the 1B range; make + // compiler happy + default: + return result; + } +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.h new file mode 100644 index 00000000000..cb908e17e9c --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/streaming.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_STREAMING_H +#define LIBCBOR_STREAMING_H + +#include "callbacks.h" +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Stateless decoder + * + * Will try parsing the \p source and will invoke the appropriate callback on + * success. Decodes one item at a time. No memory allocations occur. + * + * @param source Input buffer + * @param source_size Length of the buffer + * @param callbacks The callback bundle + * @param context An arbitrary pointer to allow for maintaining context. + */ +_CBOR_NODISCARD CBOR_EXPORT struct cbor_decoder_result cbor_stream_decode( + cbor_data source, size_t source_size, + const struct cbor_callbacks* callbacks, void* context); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_STREAMING_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.c new file mode 100644 index 00000000000..6ae96545cfe --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "strings.h" +#include <string.h> +#include "internal/memory_utils.h" +#include "internal/unicode.h" + +cbor_item_t *cbor_new_definite_string(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_STRING, + .metadata = {.string_metadata = {_CBOR_METADATA_DEFINITE, 0}}}; + return item; +} + +cbor_item_t *cbor_new_indefinite_string(void) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_STRING, + .metadata = {.string_metadata = {.type = _CBOR_METADATA_INDEFINITE, + .length = 0}}, + .data = _cbor_malloc(sizeof(struct cbor_indefinite_string_data))}; + _CBOR_DEPENDENT_NOTNULL(item, item->data); + *((struct cbor_indefinite_string_data *)item->data) = + (struct cbor_indefinite_string_data){ + .chunk_count = 0, + .chunk_capacity = 0, + .chunks = NULL, + }; + return item; +} + +cbor_item_t *cbor_build_string(const char *val) { + cbor_item_t *item = cbor_new_definite_string(); + _CBOR_NOTNULL(item); + size_t len = strlen(val); + unsigned char *handle = _cbor_malloc(len); + _CBOR_DEPENDENT_NOTNULL(item, handle); + memcpy(handle, val, len); + cbor_string_set_handle(item, handle, len); + return item; +} + +cbor_item_t *cbor_build_stringn(const char *val, size_t length) { + cbor_item_t *item = cbor_new_definite_string(); + _CBOR_NOTNULL(item); + unsigned char *handle = _cbor_malloc(length); + _CBOR_DEPENDENT_NOTNULL(item, handle); + memcpy(handle, val, length); + cbor_string_set_handle(item, handle, length); + return item; +} + +void cbor_string_set_handle(cbor_item_t *item, + cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length) { + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_definite(item)); + item->data = data; + item->metadata.string_metadata.length = length; + struct _cbor_unicode_status unicode_status; + size_t codepoint_count = + _cbor_unicode_codepoint_count(data, length, &unicode_status); + CBOR_ASSERT(codepoint_count <= length); + if (unicode_status.status == _CBOR_UNICODE_OK) { + item->metadata.string_metadata.codepoint_count = codepoint_count; + } else { + item->metadata.string_metadata.codepoint_count = 0; + } +} + +cbor_item_t **cbor_string_chunks_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); + return ((struct cbor_indefinite_string_data *)item->data)->chunks; +} + +size_t cbor_string_chunk_count(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); + return ((struct cbor_indefinite_string_data *)item->data)->chunk_count; +} + +bool cbor_string_add_chunk(cbor_item_t *item, cbor_item_t *chunk) { + CBOR_ASSERT(cbor_isa_string(item)); + CBOR_ASSERT(cbor_string_is_indefinite(item)); + struct cbor_indefinite_string_data *data = + (struct cbor_indefinite_string_data *)item->data; + if (data->chunk_count == data->chunk_capacity) { + if (!_cbor_safe_to_multiply(CBOR_BUFFER_GROWTH, data->chunk_capacity)) { + return false; + } + + size_t new_chunk_capacity = + data->chunk_capacity == 0 ? 1 + : CBOR_BUFFER_GROWTH * (data->chunk_capacity); + cbor_item_t **new_chunks_data = _cbor_realloc_multiple( + data->chunks, sizeof(cbor_item_t *), new_chunk_capacity); + + if (new_chunks_data == NULL) { + return false; + } + + data->chunk_capacity = new_chunk_capacity; + data->chunks = new_chunks_data; + } + data->chunks[data->chunk_count++] = cbor_incref(chunk); + return true; +} + +size_t cbor_string_length(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + return item->metadata.string_metadata.length; +} + +unsigned char *cbor_string_handle(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + return item->data; +} + +size_t cbor_string_codepoint_count(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + return item->metadata.string_metadata.codepoint_count; +} + +bool cbor_string_is_definite(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_string(item)); + return item->metadata.string_metadata.type == _CBOR_METADATA_DEFINITE; +} + +bool cbor_string_is_indefinite(const cbor_item_t *item) { + return !cbor_string_is_definite(item); +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.h new file mode 100644 index 00000000000..3e03f81385f --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/strings.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_STRINGS_H +#define LIBCBOR_STRINGS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * String manipulation + * ============================================================================ + */ + +/** Returns the length of the underlying string in bytes + * + * There can be fewer unicode character than bytes (see + * `cbor_string_codepoint_count`). For definite strings only. + * + * @param item a definite string + * @return length of the string. Zero if no chunk has been attached yet + */ +_CBOR_NODISCARD CBOR_EXPORT size_t cbor_string_length(const cbor_item_t *item); + +/** The number of codepoints in this string + * + * Might differ from `cbor_string_length` if there are multibyte codepoints. + * If the string data is not valid UTF-8, returns 0. + * + * @param item A string + * @return The number of codepoints in this string + */ +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_string_codepoint_count(const cbor_item_t *item); + +/** Is the string definite? + * + * @param item a string + * @return Is the string definite? + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_is_definite( + const cbor_item_t *item); + +/** Is the string indefinite? + * + * @param item a string + * @return Is the string indefinite? + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_is_indefinite( + const cbor_item_t *item); + +/** Get the handle to the underlying string + * + * Definite items only. Modifying the data is allowed. In that case, the caller + * takes responsibility for the effect on items this item might be a part of + * + * @param item A definite string + * @return The address of the underlying string. + * @return `NULL` if no data have been assigned yet. + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_mutable_data +cbor_string_handle(const cbor_item_t *item); + +/** Set the handle to the underlying string + * + * The data is assumed to be a valid UTF-8 string. If the string is non-empty + * and invalid, `cbor_string_codepoint_count` will return 0. + * + * \rst + * .. warning:: Using a pointer to a stack allocated constant is a common + * mistake. Lifetime of the string will expire when it goes out of scope and + * the CBOR item will be left inconsistent. + * \endrst + * + * @param item A definite string + * @param data The memory block. The caller gives up the ownership of the block. + * libcbor will deallocate it when appropriate using its free function + * @param length Length of the data block + */ +CBOR_EXPORT void cbor_string_set_handle( + cbor_item_t *item, cbor_mutable_data CBOR_RESTRICT_POINTER data, + size_t length); + +/** Get the handle to the array of chunks + * + * Manipulations with the memory block (e.g. sorting it) are allowed, but the + * validity and the number of chunks must be retained. + * + * @param item A indefinite string + * @return array of #cbor_string_chunk_count definite strings + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t **cbor_string_chunks_handle( + const cbor_item_t *item); + +/** Get the number of chunks this string consist of + * + * @param item A indefinite string + * @return The chunk count. 0 for freshly created items. + */ +_CBOR_NODISCARD CBOR_EXPORT size_t +cbor_string_chunk_count(const cbor_item_t *item); + +/** Appends a chunk to the string + * + * Indefinite strings only. + * + * May realloc the chunk storage. + * + * @param item An indefinite string + * @param chunk A definite string item. Its reference count will be increased + * by one. + * @return `true` on success. `false` on memory allocation failure. In that + * case, the refcount of @p `chunk` is not increased and the @p `item` is left + * intact. + */ +_CBOR_NODISCARD CBOR_EXPORT bool cbor_string_add_chunk(cbor_item_t *item, + cbor_item_t *chunk); + +/** Creates a new definite string + * + * The handle is initialized to `NULL` and length to 0 + * + * @return Reference to the new string item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_definite_string(void); + +/** Creates a new indefinite string + * + * The chunks array is initialized to `NULL` and chunkcount to 0 + * + * @return Reference to the new string item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_indefinite_string(void); + +/** Creates a new string and initializes it + * + * The data from `val` will be copied to a newly allocated memory block. + * + * Note that valid UTF-8 strings do not contain null bytes, so this routine is + * correct for all valid inputs. If the input is not guaranteed to be valid, + * use `cbor_build_stringn` instead. + * + * @param val A null-terminated UTF-8 string + * @return Reference to the new string item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_string(const char *val); + +/** Creates a new string and initializes it + * + * The data from `handle` will be copied to a newly allocated memory block. + * + * All @p `length` bytes will be stored in the string, even if there are null + * bytes or invalid UTF-8 sequences. + * + * @param val A UTF-8 string, at least @p `length` bytes long + * @param length Length (in bytes) of the string passed in @p `val`. + * @return Reference to the new string item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_stringn(const char *val, + size_t length); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_STRINGS_H diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.c b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.c new file mode 100644 index 00000000000..3f3edb0b0e1 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include "tags.h" + +cbor_item_t *cbor_new_tag(uint64_t value) { + cbor_item_t *item = _cbor_malloc(sizeof(cbor_item_t)); + _CBOR_NOTNULL(item); + + *item = (cbor_item_t){ + .refcount = 1, + .type = CBOR_TYPE_TAG, + .metadata = {.tag_metadata = {.value = value, .tagged_item = NULL}}, + .data = NULL /* Never used */ + }; + return item; +} + +cbor_item_t *cbor_tag_item(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_tag(item)); + return cbor_incref(item->metadata.tag_metadata.tagged_item); +} + +uint64_t cbor_tag_value(const cbor_item_t *item) { + CBOR_ASSERT(cbor_isa_tag(item)); + return item->metadata.tag_metadata.value; +} + +void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item) { + CBOR_ASSERT(cbor_isa_tag(item)); + cbor_incref(tagged_item); + item->metadata.tag_metadata.tagged_item = tagged_item; +} + +cbor_item_t *cbor_build_tag(uint64_t value, cbor_item_t *item) { + cbor_item_t *res = cbor_new_tag(value); + if (res == NULL) { + return NULL; + } + cbor_tag_set_item(res, item); + return res; +} diff --git a/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.h b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.h new file mode 100644 index 00000000000..a7365df1020 --- /dev/null +++ b/contrib/restricted/aws/aws-c-common/source/external/libcbor/cbor/tags.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014-2020 Pavel Kalvoda <[email protected]> + * + * libcbor is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef LIBCBOR_TAGS_H +#define LIBCBOR_TAGS_H + +#include "cbor/cbor_export.h" +#include "cbor/common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * ============================================================================ + * Tag manipulation + * ============================================================================ + */ + +/** Create a new tag + * + * @param value The tag value. Please consult the tag repository + * @return Reference to the new tag item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_new_tag(uint64_t value); + +/** Get the tagged item + * + * @param item A tag + * @return Reference to the tagged item + * + * Increases the reference count of the underlying item. The returned reference + * must be released using #cbor_decref. + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_tag_item(const cbor_item_t *item); + +/** Get tag value + * + * @param item A tag + * @return The tag value. Please consult the tag repository + */ +_CBOR_NODISCARD CBOR_EXPORT uint64_t cbor_tag_value(const cbor_item_t *item); + +/** Set the tagged item + * + * @param item A tag + * @param tagged_item The item to tag. Its reference count will be increased + * by one. + */ +CBOR_EXPORT void cbor_tag_set_item(cbor_item_t *item, cbor_item_t *tagged_item); + +/** Build a new tag + * + * @param item The item to tag. Its reference count will be increased by + * one. + * @param value Tag value + * @return Reference to the new tag item. The item's reference count is + * initialized to one. + * @return `NULL` if memory allocation fails + */ +_CBOR_NODISCARD CBOR_EXPORT cbor_item_t *cbor_build_tag(uint64_t value, + cbor_item_t *item); + +#ifdef __cplusplus +} +#endif + +#endif // LIBCBOR_TAGS_H diff --git a/contrib/restricted/aws/aws-c-common/source/host_utils.c b/contrib/restricted/aws/aws-c-common/source/host_utils.c index 6cd26ba88e2..ba1520d3354 100644 --- a/contrib/restricted/aws/aws-c-common/source/host_utils.c +++ b/contrib/restricted/aws/aws-c-common/source/host_utils.c @@ -20,14 +20,6 @@ static bool s_is_ipv6_char(uint8_t value) { return aws_isxdigit(value) || value == ':'; } -static bool s_starts_with(struct aws_byte_cursor cur, uint8_t ch) { - return cur.len > 0 && cur.ptr[0] == ch; -} - -static bool s_ends_with(struct aws_byte_cursor cur, uint8_t ch) { - return cur.len > 0 && cur.ptr[cur.len - 1] == ch; -} - bool aws_host_utils_is_ipv4(struct aws_byte_cursor host) { if (host.len > AWS_IPV4_STR_LEN - 1) { return false; @@ -69,47 +61,55 @@ static struct aws_byte_cursor s_percent_uri_enc = AWS_BYTE_CUR_INIT_FROM_STRING_ * ipv6 literal can be scoped by to zone by appending % followed by zone name * ( does not look like there is length reqs on zone name length. this * implementation enforces that its > 1 ) - * ipv6 can be embedded in url, in which case it must be wrapped inside [] - * and % be uri encoded as %25. + * ipv6 can be embedded in url, in which case % must be uri encoded as %25. * Implementation is fairly trivial and just iterates through the string * keeping track of the spec above. + * Note: there is no single rfc for IPv6 address - base format defined in RFC 5952, + * zoneId and uri extensions defined in RFC 6874 and RFC 3986 */ bool aws_host_utils_is_ipv6(struct aws_byte_cursor host, bool is_uri_encoded) { if (host.len == 0) { return false; } - if (is_uri_encoded) { - if (!s_starts_with(host, '[') || !s_ends_with(host, ']')) { - return false; - } - aws_byte_cursor_advance(&host, 1); - --host.len; - } - struct aws_byte_cursor substr = {0}; /* first split is required ipv6 part */ bool is_split = aws_byte_cursor_next_split(&host, '%', &substr); AWS_ASSERT(is_split); /* function is guaranteed to return at least one split */ - if (!is_split || substr.len == 0 || s_ends_with(substr, ':') || - !aws_byte_cursor_satisfies_pred(&substr, s_is_ipv6_char)) { + if (!is_split || substr.len < 2 || substr.len > 39 || !aws_byte_cursor_satisfies_pred(&substr, s_is_ipv6_char)) { + return false; + } + + if ((substr.ptr[0] == ':' && substr.ptr[1] != ':') || /* no single colon at start */ + (substr.ptr[substr.len - 1] == ':' && substr.ptr[substr.len - 2] != ':')) { /* no single colon at end */ return false; } - uint8_t group_count = 0; + uint8_t group_count = 1; /* string itself is the first group and then every new : we encounter is new group */ + uint8_t digit_count = 0; bool has_double_colon = false; - struct aws_byte_cursor group = {0}; - while (aws_byte_cursor_next_split(&substr, ':', &group)) { - ++group_count; - if (group_count > 8 || /* too many groups */ - group.len > 4 || /* too many chars in group */ - (has_double_colon && group.len == 0 && group_count > 2)) { /* only one double colon allowed */ - return false; + for (size_t i = 0; i < substr.len; ++i) { + if (substr.ptr[i] == ':') { + ++group_count; + digit_count = 0; + + if (i > 0 && substr.ptr[i - 1] == ':') { + if (has_double_colon) { /* one double colon max */ + return false; + } + has_double_colon = true; + --group_count; /* avoid double counting groups */ + } + } else { + ++digit_count; } - has_double_colon = has_double_colon || group.len == 0; + if (digit_count > 4 || /* too many digits in group */ + group_count > 8) { /* too many groups */ + return false; + } } /* second split is optional zone part */ @@ -123,5 +123,5 @@ bool aws_host_utils_is_ipv6(struct aws_byte_cursor host, bool is_uri_encoded) { } } - return has_double_colon ? group_count < 7 : group_count == 8; + return has_double_colon ? group_count <= 8 : group_count == 8; } diff --git a/contrib/restricted/aws/aws-c-common/source/json.c b/contrib/restricted/aws/aws-c-common/source/json.c index 326354d628e..2f1630ea287 100644 --- a/contrib/restricted/aws/aws-c-common/source/json.c +++ b/contrib/restricted/aws/aws-c-common/source/json.c @@ -7,7 +7,7 @@ #include <aws/common/string.h> #include <aws/common/json.h> -#include <aws/common/private/json_impl.h> +#include <aws/common/private/external_module_impl.h> #include "external/cJSON.h" @@ -21,6 +21,12 @@ struct aws_json_value *aws_json_value_new_string(struct aws_allocator *allocator return ret_val; } +struct aws_json_value *aws_json_value_new_string_from_c_str(struct aws_allocator *allocator, const char *string) { + (void)allocator; /* No need for allocator. It is overriden through hooks. */ + void *ret_val = cJSON_CreateString(string); + return ret_val; +} + struct aws_json_value *aws_json_value_new_number(struct aws_allocator *allocator, double number) { (void)allocator; // prevent warnings over unused parameter return (void *)cJSON_CreateNumber(number); @@ -78,92 +84,95 @@ int aws_json_value_add_to_object( struct aws_byte_cursor key, struct aws_json_value *value) { - int result = AWS_OP_ERR; struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key); + int result = aws_json_value_add_to_object_c_str(object, aws_string_c_str(tmp), value); + + aws_string_destroy_secure(tmp); + return result; +} + +int aws_json_value_add_to_object_c_str(struct aws_json_value *object, const char *key, struct aws_json_value *value) { struct cJSON *cjson = (struct cJSON *)object; if (!cJSON_IsObject(cjson)) { - aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - goto done; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); } struct cJSON *cjson_value = (struct cJSON *)value; if (cJSON_IsInvalid(cjson_value)) { - result = aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - goto done; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); } - if (cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) { - goto done; + if (cJSON_HasObjectItem(cjson, key)) { + return AWS_OP_ERR; } - cJSON_AddItemToObject(cjson, aws_string_c_str(tmp), cjson_value); - result = AWS_OP_SUCCESS; - -done: - aws_string_destroy_secure(tmp); - return result; + cJSON_AddItemToObject(cjson, key, cjson_value); + return AWS_OP_SUCCESS; } struct aws_json_value *aws_json_value_get_from_object(const struct aws_json_value *object, struct aws_byte_cursor key) { - void *return_value = NULL; struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key); + void *return_value = aws_json_value_get_from_object_c_str(object, aws_string_c_str(tmp)); + aws_string_destroy_secure(tmp); + return return_value; +} + +struct aws_json_value *aws_json_value_get_from_object_c_str(const struct aws_json_value *object, const char *key) { const struct cJSON *cjson = (const struct cJSON *)object; if (!cJSON_IsObject(cjson)) { aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - goto done; + return NULL; } - if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) { - goto done; + if (!cJSON_HasObjectItem(cjson, key)) { + return NULL; } - return_value = (void *)cJSON_GetObjectItem(cjson, aws_string_c_str(tmp)); - -done: - aws_string_destroy_secure(tmp); - return return_value; + return (void *)cJSON_GetObjectItem(cjson, key); } bool aws_json_value_has_key(const struct aws_json_value *object, struct aws_byte_cursor key) { struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key); - bool result = false; + bool result = aws_json_value_has_key_c_str(object, aws_string_c_str(tmp)); + + aws_string_destroy_secure(tmp); + return result; +} +bool aws_json_value_has_key_c_str(const struct aws_json_value *object, const char *key) { const struct cJSON *cjson = (const struct cJSON *)object; if (!cJSON_IsObject(cjson)) { - goto done; + return false; } - if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) { - goto done; + if (!cJSON_HasObjectItem(cjson, key)) { + return false; } - result = true; -done: - aws_string_destroy_secure(tmp); - return result; + return true; } int aws_json_value_remove_from_object(struct aws_json_value *object, struct aws_byte_cursor key) { - int result = AWS_OP_ERR; struct aws_string *tmp = aws_string_new_from_cursor(s_aws_json_module_allocator, &key); + int result = aws_json_value_remove_from_object_c_str(object, aws_string_c_str(tmp)); + aws_string_destroy_secure(tmp); + return result; +} + +int aws_json_value_remove_from_object_c_str(struct aws_json_value *object, const char *key) { struct cJSON *cjson = (struct cJSON *)object; if (!cJSON_IsObject(cjson)) { - aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - goto done; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); } - if (!cJSON_HasObjectItem(cjson, aws_string_c_str(tmp))) { - goto done; + if (!cJSON_HasObjectItem(cjson, key)) { + return AWS_OP_ERR; } - cJSON_DeleteItemFromObject(cjson, aws_string_c_str(tmp)); - result = AWS_OP_SUCCESS; - -done: - aws_string_destroy_secure(tmp); - return result; + cJSON_DeleteItemFromObject(cjson, key); + return AWS_OP_SUCCESS; } int aws_json_const_iterate_object( diff --git a/contrib/restricted/aws/aws-c-common/source/memtrace.c b/contrib/restricted/aws/aws-c-common/source/memtrace.c index 9c5bff60cc0..ee1f291d71e 100644 --- a/contrib/restricted/aws/aws-c-common/source/memtrace.c +++ b/contrib/restricted/aws/aws-c-common/source/memtrace.c @@ -131,29 +131,43 @@ static void s_alloc_tracer_track(struct alloc_tracer *tracer, void *ptr, size_t aws_high_res_clock_get_ticks(&alloc->time); if (tracer->level == AWS_MEMTRACE_STACKS) { - /* capture stack frames, skip 2 for this function and the allocation vtable function */ + /* capture stack frames, + * skip 2 for this function and the allocation vtable function if we have a full stack trace + * and otherwise just capture what ever stack trace we got + */ AWS_VARIABLE_LENGTH_ARRAY(void *, stack_frames, (FRAMES_TO_SKIP + tracer->frames_per_stack)); size_t stack_depth = aws_backtrace(stack_frames, FRAMES_TO_SKIP + tracer->frames_per_stack); - if (stack_depth) { - /* hash the stack pointers */ - struct aws_byte_cursor stack_cursor = - aws_byte_cursor_from_array(stack_frames, stack_depth * sizeof(void *)); - uint64_t stack_id = aws_hash_byte_cursor_ptr(&stack_cursor); - alloc->stack = stack_id; /* associate the stack with the alloc */ - - aws_mutex_lock(&tracer->mutex); - struct aws_hash_element *item = NULL; - int was_created = 0; - AWS_FATAL_ASSERT( - AWS_OP_SUCCESS == - aws_hash_table_create(&tracer->stacks, (void *)(uintptr_t)stack_id, &item, &was_created)); - /* If this is a new stack, save it to the hash */ - if (was_created) { - struct stack_trace *stack = aws_mem_calloc( - aws_default_allocator(), - 1, - sizeof(struct stack_trace) + (sizeof(void *) * tracer->frames_per_stack)); - AWS_FATAL_ASSERT(stack); + AWS_FATAL_ASSERT(stack_depth > 0); + + /* hash the stack pointers */ + struct aws_byte_cursor stack_cursor = aws_byte_cursor_from_array(stack_frames, stack_depth * sizeof(void *)); + uint64_t stack_id = aws_hash_byte_cursor_ptr(&stack_cursor); + alloc->stack = stack_id; /* associate the stack with the alloc */ + + aws_mutex_lock(&tracer->mutex); + struct aws_hash_element *item = NULL; + int was_created = 0; + AWS_FATAL_ASSERT( + AWS_OP_SUCCESS == aws_hash_table_create(&tracer->stacks, (void *)(uintptr_t)stack_id, &item, &was_created)); + /* If this is a new stack, save it to the hash */ + if (was_created) { + struct stack_trace *stack = aws_mem_calloc( + aws_default_allocator(), 1, sizeof(struct stack_trace) + (sizeof(void *) * tracer->frames_per_stack)); + AWS_FATAL_ASSERT(stack); + /** + * Optimizations can affect the number of frames we get and in pathological cases we can + * get fewer than FRAMES_TO_SKIP frames, but always at least 1 because code has to start somewhere. + * (looking at you gcc with -O3 on aarch64) + * With optimizations on we cannot trust the stack trace too much. + * Memtracer makes an assumption that stack trace will be available in all cases if stack trace api + * works. So in the pathological case of stack_depth <= FRAMES_TO_SKIP lets record all the frames we + * have, to at least have an anchor for where allocation is comming from, however inaccurate it is. + */ + if (stack_depth <= FRAMES_TO_SKIP) { + memcpy((void **)&stack->frames[0], &stack_frames[0], (stack_depth) * sizeof(void *)); + stack->depth = stack_depth; + item->value = stack; + } else { memcpy( (void **)&stack->frames[0], &stack_frames[FRAMES_TO_SKIP], @@ -161,8 +175,9 @@ static void s_alloc_tracer_track(struct alloc_tracer *tracer, void *ptr, size_t stack->depth = stack_depth - FRAMES_TO_SKIP; item->value = stack; } - aws_mutex_unlock(&tracer->mutex); } + + aws_mutex_unlock(&tracer->mutex); } aws_mutex_lock(&tracer->mutex); diff --git a/contrib/restricted/aws/aws-c-common/source/posix/clock.c b/contrib/restricted/aws/aws-c-common/source/posix/clock.c index b2c3bc3f0e7..4ca0a47ba37 100644 --- a/contrib/restricted/aws/aws-c-common/source/posix/clock.c +++ b/contrib/restricted/aws/aws-c-common/source/posix/clock.c @@ -9,7 +9,9 @@ static const uint64_t NS_PER_SEC = 1000000000; -#if defined(CLOCK_MONOTONIC_RAW) +#if defined(CLOCK_BOOTTIME) +# define HIGH_RES_CLOCK CLOCK_BOOTTIME +#elif defined(CLOCK_MONOTONIC_RAW) # define HIGH_RES_CLOCK CLOCK_MONOTONIC_RAW #else # define HIGH_RES_CLOCK CLOCK_MONOTONIC @@ -47,7 +49,7 @@ static int (*s_gettime_fn)(clockid_t clock_id, struct timespec *tp) = NULL; static void s_do_osx_loads(void *user_data) { (void)user_data; - s_gettime_fn = (int (*)(clockid_t clock_id, struct timespec * tp)) dlsym(RTLD_DEFAULT, "clock_gettime"); + s_gettime_fn = (int (*)(clockid_t clock_id, struct timespec *tp))dlsym(RTLD_DEFAULT, "clock_gettime"); } int aws_high_res_clock_get_ticks(uint64_t *timestamp) { diff --git a/contrib/restricted/aws/aws-c-common/source/posix/cross_process_lock.c b/contrib/restricted/aws/aws-c-common/source/posix/cross_process_lock.c index 1ef5d2b5fe4..f9483418443 100644 --- a/contrib/restricted/aws/aws-c-common/source/posix/cross_process_lock.c +++ b/contrib/restricted/aws/aws-c-common/source/posix/cross_process_lock.c @@ -133,7 +133,6 @@ cleanup: void aws_cross_process_lock_release(struct aws_cross_process_lock *instance_lock) { if (instance_lock) { - flock(instance_lock->locked_fd, LOCK_UN); close(instance_lock->locked_fd); AWS_LOGF_TRACE(AWS_LS_COMMON_GENERAL, "static: Lock file released for fd %d", instance_lock->locked_fd); aws_mem_release(instance_lock->allocator, instance_lock); diff --git a/contrib/restricted/aws/aws-c-common/source/posix/environment.c b/contrib/restricted/aws/aws-c-common/source/posix/environment.c index f4b69caea25..ba1f8bb4425 100644 --- a/contrib/restricted/aws/aws-c-common/source/posix/environment.c +++ b/contrib/restricted/aws/aws-c-common/source/posix/environment.c @@ -8,6 +8,26 @@ #include <aws/common/string.h> #include <stdlib.h> +struct aws_string *aws_get_env(struct aws_allocator *allocator, const char *name) { + + const char *value = getenv(name); + if (value == NULL) { + return NULL; + } + + return aws_string_new_from_c_str(allocator, value); +} + +struct aws_string *aws_get_env_nonempty(struct aws_allocator *allocator, const char *name) { + + const char *value = getenv(name); + if (value == NULL || value[0] == '\0') { + return NULL; + } + + return aws_string_new_from_c_str(allocator, value); +} + int aws_get_environment_value( struct aws_allocator *allocator, const struct aws_string *variable_name, diff --git a/contrib/restricted/aws/aws-c-common/source/posix/thread.c b/contrib/restricted/aws/aws-c-common/source/posix/thread.c index af7fac84cf9..34b5dbe9486 100644 --- a/contrib/restricted/aws/aws-c-common/source/posix/thread.c +++ b/contrib/restricted/aws/aws-c-common/source/posix/thread.c @@ -275,6 +275,25 @@ int aws_thread_launch( if (attr_return) { goto cleanup; } + } else if (!options->stack_size) { + /** + * On some systems, the default stack size is too low (128KB on musl at the time of writing this), which can + * cause stack overflow when the dependency chain is long. Increase the stack size to at + * least 1MB, which is the default on Windows. + */ + size_t min_stack_size = (size_t)1 * 1024 * 1024; + size_t current_stack_size; + attr_return = pthread_attr_getstacksize(attributes_ptr, ¤t_stack_size); + if (attr_return) { + goto cleanup; + } + + if (current_stack_size < min_stack_size) { + attr_return = pthread_attr_setstacksize(attributes_ptr, min_stack_size); + if (attr_return) { + goto cleanup; + } + } } /* AFAIK you can't set thread affinity on apple platforms, and it doesn't really matter since all memory diff --git a/contrib/restricted/aws/aws-c-common/source/priority_queue.c b/contrib/restricted/aws/aws-c-common/source/priority_queue.c index fcea718bf2c..2157ffd0ae4 100644 --- a/contrib/restricted/aws/aws-c-common/source/priority_queue.c +++ b/contrib/restricted/aws/aws-c-common/source/priority_queue.c @@ -7,7 +7,7 @@ #include <string.h> -#define PARENT_OF(index) (((index)&1) ? (index) >> 1 : (index) > 1 ? ((index)-2) >> 1 : 0) +#define PARENT_OF(index) (((index) & 1) ? (index) >> 1 : (index) > 1 ? ((index) - 2) >> 1 : 0) #define LEFT_OF(index) (((index) << 1) + 1) #define RIGHT_OF(index) (((index) << 1) + 2) diff --git a/contrib/restricted/aws/aws-c-common/source/promise.c b/contrib/restricted/aws/aws-c-common/source/promise.c deleted file mode 100644 index 7c8572457ea..00000000000 --- a/contrib/restricted/aws/aws-c-common/source/promise.c +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/common/condition_variable.h> -#include <aws/common/mutex.h> -#include <aws/common/promise.h> -#include <aws/common/ref_count.h> - -struct aws_promise { - struct aws_allocator *allocator; - struct aws_mutex mutex; - struct aws_condition_variable cv; - struct aws_ref_count rc; - bool complete; - int error_code; - void *value; - - /* destructor for value, will be invoked if the value is not taken */ - void (*dtor)(void *); -}; - -static void s_aws_promise_dtor(void *ptr) { - struct aws_promise *promise = ptr; - aws_condition_variable_clean_up(&promise->cv); - aws_mutex_clean_up(&promise->mutex); - if (promise->value && promise->dtor) { - promise->dtor(promise->value); - } - aws_mem_release(promise->allocator, promise); -} - -struct aws_promise *aws_promise_new(struct aws_allocator *allocator) { - struct aws_promise *promise = aws_mem_calloc(allocator, 1, sizeof(struct aws_promise)); - promise->allocator = allocator; - aws_ref_count_init(&promise->rc, promise, s_aws_promise_dtor); - aws_mutex_init(&promise->mutex); - aws_condition_variable_init(&promise->cv); - return promise; -} - -struct aws_promise *aws_promise_acquire(struct aws_promise *promise) { - aws_ref_count_acquire(&promise->rc); - return promise; -} - -void aws_promise_release(struct aws_promise *promise) { - aws_ref_count_release(&promise->rc); -} - -static bool s_promise_completed(void *user_data) { - struct aws_promise *promise = user_data; - return promise->complete; -} - -void aws_promise_wait(struct aws_promise *promise) { - aws_mutex_lock(&promise->mutex); - aws_condition_variable_wait_pred(&promise->cv, &promise->mutex, s_promise_completed, promise); - aws_mutex_unlock(&promise->mutex); -} - -bool aws_promise_wait_for(struct aws_promise *promise, size_t nanoseconds) { - aws_mutex_lock(&promise->mutex); - aws_condition_variable_wait_for_pred( - &promise->cv, &promise->mutex, (int64_t)nanoseconds, s_promise_completed, promise); - const bool complete = promise->complete; - aws_mutex_unlock(&promise->mutex); - return complete; -} - -bool aws_promise_is_complete(struct aws_promise *promise) { - aws_mutex_lock(&promise->mutex); - const bool complete = promise->complete; - aws_mutex_unlock(&promise->mutex); - return complete; -} - -void aws_promise_complete(struct aws_promise *promise, void *value, void (*dtor)(void *)) { - aws_mutex_lock(&promise->mutex); - AWS_FATAL_ASSERT(!promise->complete && "aws_promise_complete: cannot complete a promise more than once"); - promise->value = value; - promise->dtor = dtor; - promise->complete = true; - /* Notify before unlocking to prevent a race condition where the recipient spuriously - * awakens after the unlock, sees a fulfilled promise, and attempts to free its resources - * before the notification has actually occured. */ - aws_condition_variable_notify_all(&promise->cv); - aws_mutex_unlock(&promise->mutex); -} - -void aws_promise_fail(struct aws_promise *promise, int error_code) { - AWS_FATAL_ASSERT(error_code != 0 && "aws_promise_fail: cannot fail a promise with a 0 error_code"); - aws_mutex_lock(&promise->mutex); - AWS_FATAL_ASSERT(!promise->complete && "aws_promise_fail: cannot complete a promise more than once"); - promise->error_code = error_code; - promise->complete = true; - aws_condition_variable_notify_all(&promise->cv); - aws_mutex_unlock(&promise->mutex); -} - -int aws_promise_error_code(struct aws_promise *promise) { - AWS_FATAL_ASSERT(aws_promise_is_complete(promise)); - return promise->error_code; -} - -void *aws_promise_value(struct aws_promise *promise) { - AWS_FATAL_ASSERT(aws_promise_is_complete(promise)); - return promise->value; -} - -void *aws_promise_take_value(struct aws_promise *promise) { - AWS_FATAL_ASSERT(aws_promise_is_complete(promise)); - void *value = promise->value; - promise->value = NULL; - promise->dtor = NULL; - return value; -} diff --git a/contrib/restricted/aws/aws-c-common/source/string.c b/contrib/restricted/aws/aws-c-common/source/string.c index 2fd79123057..e68f6b284dc 100644 --- a/contrib/restricted/aws/aws-c-common/source/string.c +++ b/contrib/restricted/aws/aws-c-common/source/string.c @@ -416,7 +416,12 @@ bool aws_byte_buf_write_from_whole_string( * Creates an aws_byte_cursor from an existing string. */ struct aws_byte_cursor aws_byte_cursor_from_string(const struct aws_string *src) { - AWS_PRECONDITION(aws_string_is_valid(src)); + if (!src) { + struct aws_byte_cursor cursor; + AWS_ZERO_STRUCT(cursor); + return cursor; + } + return aws_byte_cursor_from_array(aws_string_bytes(src), src->len); } diff --git a/contrib/restricted/aws/aws-c-common/source/task_scheduler.c b/contrib/restricted/aws/aws-c-common/source/task_scheduler.c index bca150e39bf..9076ae249a9 100644 --- a/contrib/restricted/aws/aws-c-common/source/task_scheduler.c +++ b/contrib/restricted/aws/aws-c-common/source/task_scheduler.c @@ -33,7 +33,7 @@ const char *aws_task_status_to_c_str(enum aws_task_status status) { void aws_task_run(struct aws_task *task, enum aws_task_status status) { AWS_ASSERT(task->fn); - AWS_LOGF_DEBUG( + AWS_LOGF_TRACE( AWS_LS_COMMON_TASK_SCHEDULER, "id=%p: Running %s task with %s status", (void *)task, @@ -129,7 +129,7 @@ void aws_task_scheduler_schedule_now(struct aws_task_scheduler *scheduler, struc AWS_ASSERT(task); AWS_ASSERT(task->fn); - AWS_LOGF_DEBUG( + AWS_LOGF_TRACE( AWS_LS_COMMON_TASK_SCHEDULER, "id=%p: Scheduling %s task for immediate execution", (void *)task, @@ -152,7 +152,7 @@ void aws_task_scheduler_schedule_future( AWS_ASSERT(task); AWS_ASSERT(task->fn); - AWS_LOGF_DEBUG( + AWS_LOGF_TRACE( AWS_LS_COMMON_TASK_SCHEDULER, "id=%p: Scheduling %s task for future execution at time %" PRIu64, (void *)task, diff --git a/contrib/restricted/aws/aws-c-common/source/uri.c b/contrib/restricted/aws/aws-c-common/source/uri.c index f9ecc9d77ed..88a7f91ea19 100644 --- a/contrib/restricted/aws/aws-c-common/source/uri.c +++ b/contrib/restricted/aws/aws-c-common/source/uri.c @@ -282,8 +282,9 @@ static void s_parse_scheme(struct uri_parser *parser, struct aws_byte_cursor *st return; } - /* make sure we didn't just pick up the port by mistake */ - if ((size_t)(location_of_colon - str->ptr) < str->len && *(location_of_colon + 1) != '/') { + /* Ensure location_of_colon is not the last character before checking *(location_of_colon + 1) */ + if ((size_t)(location_of_colon - str->ptr) + 1 >= str->len || *(location_of_colon + 1) != '/') { + /* make sure we didn't just pick up the port by mistake */ parser->state = ON_AUTHORITY; return; } @@ -364,7 +365,9 @@ static void s_parse_authority(struct uri_parser *parser, struct aws_byte_cursor * IPv6 literals and only search for port delimiter after closing bracket.*/ const uint8_t *port_search_start = authority_parse_csr.ptr; size_t port_search_len = authority_parse_csr.len; + bool is_IPv6_literal = false; if (authority_parse_csr.len > 0 && authority_parse_csr.ptr[0] == '[') { + is_IPv6_literal = true; port_search_start = memchr(authority_parse_csr.ptr, ']', authority_parse_csr.len); if (!port_search_start) { parser->state = ERROR; @@ -375,17 +378,24 @@ static void s_parse_authority(struct uri_parser *parser, struct aws_byte_cursor } const uint8_t *port_delim = memchr(port_search_start, ':', port_search_len); - + /* + * RFC-3986 section 3.2.2: A host identified by an IPv6 literal address is represented inside square + * brackets. + * Ignore the square brackets. + */ + parser->uri->host_name = authority_parse_csr; + if (is_IPv6_literal) { + aws_byte_cursor_advance(&parser->uri->host_name, 1); + parser->uri->host_name.len--; + } if (!port_delim) { parser->uri->port = 0; - parser->uri->host_name = authority_parse_csr; return; } - parser->uri->host_name.ptr = authority_parse_csr.ptr; - parser->uri->host_name.len = port_delim - authority_parse_csr.ptr; - - size_t port_len = authority_parse_csr.len - parser->uri->host_name.len - 1; + size_t host_name_length_correction = is_IPv6_literal ? 2 : 0; + parser->uri->host_name.len = port_delim - authority_parse_csr.ptr - host_name_length_correction; + size_t port_len = authority_parse_csr.len - parser->uri->host_name.len - 1 - host_name_length_correction; port_delim += 1; uint64_t port_u64 = 0; diff --git a/contrib/restricted/aws/aws-c-common/source/xml_parser.c b/contrib/restricted/aws/aws-c-common/source/xml_parser.c index e1b5807401d..7675bff3017 100644 --- a/contrib/restricted/aws/aws-c-common/source/xml_parser.c +++ b/contrib/restricted/aws/aws-c-common/source/xml_parser.c @@ -40,6 +40,8 @@ static int s_load_node_decl( AWS_PRECONDITION(decl_body); AWS_PRECONDITION(node); + node->is_empty = decl_body->ptr[decl_body->len - 1] == '/'; + struct aws_array_list splits; AWS_ZERO_STRUCT(splits); @@ -158,6 +160,14 @@ int s_advance_to_closing_tag( AWS_PRECONDITION(parser); AWS_PRECONDITION(node); + if (node->is_empty) { + if (out_body) { + out_body->ptr = NULL; + out_body->len = 0; + } + return AWS_OP_SUCCESS; + } + /* currently the max node name is 256 characters. This is arbitrary, but should be enough * for our uses. If we ever generalize this, we'll have to come back and rethink this. */ uint8_t name_close[MAX_NAME_LEN + NODE_CLOSE_OVERHEAD] = {0}; |