From 3f970dc3b350b9f3b68a86c654c283abc9b8300b Mon Sep 17 00:00:00 2001 From: Eduardo Silva Date: Tue, 21 Jul 2026 12:45:58 -0600 Subject: [PATCH] variant_utils: tighten MessagePack nesting limit Signed-off-by: Eduardo Silva --- include/ctraces/ctr_variant_utils.h | 14 ++++--- tests/decoding.c | 59 +++++++++++++++++++++++++---- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/include/ctraces/ctr_variant_utils.h b/include/ctraces/ctr_variant_utils.h index ce5ccbe..4de45f0 100644 --- a/include/ctraces/ctr_variant_utils.h +++ b/include/ctraces/ctr_variant_utils.h @@ -27,7 +27,7 @@ #define CFL_VARIANT_UTILS_INITIAL_ARRAY_SIZE 100 #define CFL_VARIANT_UTILS_SERIALIZED_ARRAY_SIZE_LIMIT 100000 #define CFL_VARIANT_UTILS_SERIALIZED_MAP_SIZE_LIMIT 100000 -#define CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH 64 +#define CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH 32 #define CFL_VARIANT_UTILS_MAXIMUM_KEY_LENGTH (1024 * 1000) /* These are the only functions meant for general use, @@ -246,6 +246,10 @@ static inline int unpack_cfl_array_depth(mpack_reader_t *reader, size_t index; mpack_tag_t tag; + if (depth >= CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH) { + return -2; + } + result = unpack_cfl_variant_read_tag(reader, &tag, mpack_type_array); if (result != 0) { @@ -318,6 +322,10 @@ static inline int unpack_cfl_kvlist_depth(mpack_reader_t *reader, size_t index; mpack_tag_t tag; + if (depth >= CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH) { + return -2; + } + result = unpack_cfl_variant_read_tag(reader, &tag, mpack_type_map); if (result != 0) { @@ -670,10 +678,6 @@ static inline int unpack_cfl_variant_depth(mpack_reader_t *reader, int result; mpack_tag_t tag; - if (depth >= CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH) { - return -1; - } - tag = mpack_peek_tag(reader); if (mpack_ok != mpack_reader_error(reader)) { diff --git a/tests/decoding.c b/tests/decoding.c index e21a4ff..04239b9 100644 --- a/tests/decoding.c +++ b/tests/decoding.c @@ -716,32 +716,75 @@ void test_msgpack_long_attribute_key() ctr_destroy(ctx); } -void test_msgpack_variant_limits() +static void check_variant_nesting_limit(int use_maps, size_t nesting_depth, + int expected_result) { char *buffer; size_t size; - int index; + size_t index; int result; mpack_writer_t writer; mpack_reader_t reader; struct cfl_variant *variant; - struct cfl_kvlist *kvlist; + buffer = NULL; + size = 0; + variant = NULL; mpack_writer_init_growable(&writer, &buffer, &size); - for (index = 0; index < CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH + 1; index++) { - mpack_start_array(&writer, 1); + + for (index = 0; index < nesting_depth; index++) { + if (use_maps) { + mpack_start_map(&writer, 1); + mpack_write_cstr(&writer, "key"); + } + else { + mpack_start_array(&writer, 1); + } } + mpack_write_i64(&writer, 1); - for (index = 0; index < CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH + 1; index++) { - mpack_finish_array(&writer); + + for (index = 0; index < nesting_depth; index++) { + if (use_maps) { + mpack_finish_map(&writer); + } + else { + mpack_finish_array(&writer); + } } + TEST_ASSERT(mpack_writer_destroy(&writer) == mpack_ok); mpack_reader_init_data(&reader, buffer, size); result = unpack_cfl_variant(&reader, &variant); - TEST_CHECK(result != 0); + TEST_CHECK((result == 0) == (expected_result == 0)); + + if (variant != NULL) { + cfl_variant_destroy(variant); + } + mpack_reader_destroy(&reader); free(buffer); +} + +void test_msgpack_variant_limits() +{ + char *buffer; + size_t size; + int result; + mpack_writer_t writer; + mpack_reader_t reader; + struct cfl_variant *variant; + struct cfl_kvlist *kvlist; + + check_variant_nesting_limit(CFL_FALSE, + CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH, 0); + check_variant_nesting_limit(CFL_FALSE, + CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH + 1, -1); + check_variant_nesting_limit(CFL_TRUE, + CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH, 0); + check_variant_nesting_limit(CFL_TRUE, + CFL_VARIANT_UTILS_MAXIMUM_NESTING_DEPTH + 1, -1); mpack_writer_init_growable(&writer, &buffer, &size); mpack_start_map(&writer, 1);