diff --git a/cpp/fory/serialization/collection_serializer.h b/cpp/fory/serialization/collection_serializer.h index a780d1c0c1..4b138b8d34 100644 --- a/cpp/fory/serialization/collection_serializer.h +++ b/cpp/fory/serialization/collection_serializer.h @@ -394,6 +394,10 @@ template inline Container read_collection_data_slow(ReadContext &ctx, uint32_t length) { Container result; if constexpr (has_reserve_v) { + if (length > ctx.max_collection_size()) { + ctx.set_error(Error::invalid_data("invalid collection size")); + return result; + } result.reserve(length); } @@ -717,6 +721,10 @@ struct Serializer< } std::vector result; + if (length > ctx.max_collection_size()) { + ctx.set_error(Error::invalid_data("invalid collection size")); + return result; + } result.reserve(length); // Fast path: no tracking, no nulls, elements have declared type diff --git a/cpp/fory/serialization/config.h b/cpp/fory/serialization/config.h index d471c39074..719b482c88 100644 --- a/cpp/fory/serialization/config.h +++ b/cpp/fory/serialization/config.h @@ -52,6 +52,13 @@ struct Config { /// When enabled, avoids duplicating shared objects and handles cycles. bool track_ref = true; + // max limits fot map,lists and collections + uint32_t max_string_length = + 64 * 1024 * 1024; // 64MB default max string length + uint32_t max_collection_size = + 10 * 1000 * 1000; // 1M default max collection size + uint32_t max_map_size = 1 * 1000 * 1000; // 1M default max map size + /// Default constructor with sensible defaults Config() = default; }; diff --git a/cpp/fory/serialization/context.h b/cpp/fory/serialization/context.h index 18e5e68bd5..cd567de7eb 100644 --- a/cpp/fory/serialization/context.h +++ b/cpp/fory/serialization/context.h @@ -359,6 +359,14 @@ class WriteContext { /// ``` class ReadContext { public: + /// get maximum allowed collection size. + inline uint32_t max_collection_size() const { + return config_->max_collection_size; + } + + /// get maximum allowed map size. + inline uint32_t max_map_size() const { return config_->max_map_size; } + /// Construct read context with configuration and type resolver. /// Takes ownership of the type resolver. explicit ReadContext(const Config &config, diff --git a/cpp/fory/serialization/map_serializer.h b/cpp/fory/serialization/map_serializer.h index 5bd9bea51b..9ea0ae0bc9 100644 --- a/cpp/fory/serialization/map_serializer.h +++ b/cpp/fory/serialization/map_serializer.h @@ -539,6 +539,10 @@ inline MapType read_map_data_fast(ReadContext &ctx, uint32_t length) { "Fast path is for non-shared-ref types only"); MapType result; + if (length > ctx.max_map_size()) { + ctx.set_error(Error::invalid_data("Invalid map size")); + return result; + } MapReserver::reserve(result, length); if (length == 0) {