]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Sanity check decompressed payload size
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 11 Mar 2026 18:59:10 +0000 (19:59 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sun, 15 Mar 2026 09:43:51 +0000 (10:43 +0100)
src/ccache/core/cacheentry.cpp
src/ccache/core/cacheentry.hpp

index 09b272888d6e38746efc3455f1ed841b8e48c763..03f8d6ae4f8b2b8dbbd2a392a626f6857b7cb419 100644 (file)
@@ -34,6 +34,7 @@
 #include <ccache/util/zstd.hpp>
 
 #include <cstring>
+#include <limits>
 
 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<uint32_t>::max();
+
 core::CacheEntryType
 cache_entry_type_from_int(const uint8_t entry_type)
 {
@@ -201,6 +209,16 @@ CacheEntry::CacheEntry(std::span<const uint8_t> 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);
index 0f989dc678ea38409867b01719a80490e7d2a005..a8e0398726d8a7121369301f6a50d3e711782a40 100644 (file)
@@ -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<const uint8_t> data);