changeset 6140:98776c72a9bc attach-custom-data

fix MD5 hashes for large memory buffers
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 30 May 2025 12:00:44 +0200
parents e030b8efe019
children 93d408173903
files NEWS OrthancFramework/Sources/Toolbox.cpp
diffstat 2 files changed, 29 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Fri May 30 11:38:18 2025 +0200
+++ b/NEWS	Fri May 30 12:00:44 2025 +0200
@@ -22,6 +22,7 @@
   - If "LimitMainDicomTagsReconstructLevel" was set, files were not transcoded if they had to.
     The "LimitMainDicomTagsReconstructLevel" configuration is now ignored when a full processing
     is required.
+* Fix computation of MD5 hashes for memory buffers whose size is larger than 2^31 bytes.
 
 
 Version 1.12.7 (2025-04-07)
--- a/OrthancFramework/Sources/Toolbox.cpp	Fri May 30 11:38:18 2025 +0200
+++ b/OrthancFramework/Sources/Toolbox.cpp	Fri May 30 12:00:44 2025 +0200
@@ -64,6 +64,7 @@
 #include <boost/algorithm/string/join.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/regex.hpp>
+#include <cassert>
 
 #if BOOST_VERSION >= 106600
 #  include <boost/uuid/detail/sha1.hpp>
@@ -245,22 +246,39 @@
   void Toolbox::MD5Context::Append(const void* data,
                                    size_t size)
   {
+    static const size_t MAX_SIZE = 128 * 1024 * 1024;
+
     if (pimpl_->done_)
     {
       throw OrthancException(ErrorCode_BadSequenceOfCalls);
     }
 
-    if (static_cast<size_t>(static_cast<int>(size)) != size)
+    const uint8_t *p = reinterpret_cast<const uint8_t*>(data);
+
+    while (size > 0)
     {
-      throw OrthancException(ErrorCode_InternalError,
-                             "The built-in implementation of MD5 does not support buffers larger than 32bits");
-    }
-
-    if (size > 0)
-    {
-      md5_append(&pimpl_->state_,
-                 reinterpret_cast<const md5_byte_t*>(data),
-                 static_cast<int>(size));
+      /**
+       * The built-in implementation of MD5 requires that "size" can
+       * be casted to "int", so we feed it by chunks of maximum
+       * 128MB. This fixes an incorrect behavior in Orthanc <= 1.12.7.
+       **/
+
+      int chunkSize;
+      if (size > MAX_SIZE)
+      {
+        chunkSize = static_cast<int>(MAX_SIZE);
+      }
+      else
+      {
+        chunkSize = static_cast<int>(size);
+      }
+
+      md5_append(&pimpl_->state_, reinterpret_cast<const md5_byte_t*>(p), chunkSize);
+
+      p += chunkSize;
+
+      assert(static_cast<size_t>(chunkSize) <= size);
+      size -= chunkSize;
     }
   }