From: Joel Rosdahl Date: Wed, 11 Mar 2026 18:59:10 +0000 (+0100) Subject: fix: Sanity check decompressed payload size X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=68e27dc730358638dcae5f346bfadca7742b5f6a;p=thirdparty%2Fccache.git fix: Sanity check decompressed payload size --- diff --git a/src/ccache/core/cacheentry.cpp b/src/ccache/core/cacheentry.cpp index 09b27288..03f8d6ae 100644 --- a/src/ccache/core/cacheentry.cpp +++ b/src/ccache/core/cacheentry.cpp @@ -34,6 +34,7 @@ #include #include +#include namespace fs = util::filesystem; @@ -55,6 +56,13 @@ const size_t k_static_header_fields_size = const size_t k_epilogue_fields_size = sizeof(uint64_t) + sizeof(uint64_t); +// Sanity cap on decompressed payload size. The current Serializer interface +// limits written payloads to uint32_t bytes (UINT32_MAX = 4 GiB - 1), so this +// cap sits just above the maximum currently writable entry size. Raise it when +// the Serializer interface is widened. +const uint64_t k_max_uncompressed_payload_size = + std::numeric_limits::max(); + core::CacheEntryType cache_entry_type_from_int(const uint8_t entry_type) { @@ -201,6 +209,16 @@ CacheEntry::CacheEntry(std::span data) if (data.size() <= non_payload_size) { throw core::Error("CacheEntry data underflow"); } + if (m_header.entry_size < non_payload_size) { + throw core::Error(FMT("Invalid entry_size in header: {} < {}", + m_header.entry_size, + non_payload_size)); + } + if (m_header.uncompressed_payload_size() > k_max_uncompressed_payload_size) { + throw core::Error(FMT("Uncompressed payload too large: {} > {}", + m_header.uncompressed_payload_size(), + k_max_uncompressed_payload_size)); + } m_payload = data.subspan(m_header.serialized_size(), data.size() - non_payload_size); m_checksum = data.last(k_epilogue_fields_size); diff --git a/src/ccache/core/cacheentry.hpp b/src/ccache/core/cacheentry.hpp index 0f989dc6..a8e03987 100644 --- a/src/ccache/core/cacheentry.hpp +++ b/src/ccache/core/cacheentry.hpp @@ -90,7 +90,7 @@ public: size_t serialized_size() const; void serialize(util::Bytes& output) const; - uint32_t uncompressed_payload_size() const; + uint64_t uncompressed_payload_size() const; private: void parse(std::span data);