# HG changeset patch # User Alain Mazy # Date 1772721624 -3600 # Node ID b7243c4efe18299dfa2beae5104aa104f092b25b # Parent f269e4778b5920e65eccb39ac5c63b3c8b993975 limit memory when uploading zip diff -r f269e4778b59 -r b7243c4efe18 OrthancFramework/Sources/Compression/ZipReader.cpp --- a/OrthancFramework/Sources/Compression/ZipReader.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancFramework/Sources/Compression/ZipReader.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -365,6 +365,59 @@ } } + // TODO-MEM: find a way to share code between these 2 overloads + bool ZipReader::ReadNextFile(std::string& filename, + MemoryManagedString& content) + { + assert(pimpl_->unzip_ != NULL); + + if (pimpl_->done_) + { + return false; + } + else + { + unz_file_info64_s info; + if (unzGetCurrentFileInfo64(pimpl_->unzip_, &info, NULL, 0, NULL, 0, NULL, 0) != 0) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + + filename.resize(info.size_filename); + if (!filename.empty() && + unzGetCurrentFileInfo64(pimpl_->unzip_, &info, &filename[0], + static_cast(filename.size()), NULL, 0, NULL, 0) != 0) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + + content.resize(info.uncompressed_size); + + if (!content.empty()) + { + if (unzOpenCurrentFile(pimpl_->unzip_) == 0) + { + bool success = (unzReadCurrentFile(pimpl_->unzip_, &content[0], + static_cast(content.size())) != 0); + + if (unzCloseCurrentFile(pimpl_->unzip_) != 0 || + !success) + { + throw OrthancException(ErrorCode_BadFileFormat); + } + } + else + { + throw OrthancException(ErrorCode_BadFileFormat, "Invalid file or unsupported compression method (e.g. Deflate64)"); + } + } + + pimpl_->done_ = (unzGoToNextFile(pimpl_->unzip_) != 0); + + return true; + } + } + ZipReader* ZipReader::CreateFromMemory(const void* buffer, size_t size) diff -r f269e4778b59 -r b7243c4efe18 OrthancFramework/Sources/Compression/ZipReader.h --- a/OrthancFramework/Sources/Compression/ZipReader.h Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancFramework/Sources/Compression/ZipReader.h Thu Mar 05 15:40:24 2026 +0100 @@ -43,6 +43,7 @@ #include #include #include +#include "../MemoryManagedString.h" #if ORTHANC_SANDBOXED != 1 # include @@ -69,7 +70,10 @@ bool ReadNextFile(std::string& filename, std::string& content); - + + bool ReadNextFile(std::string& filename, + MemoryManagedString& content); + static ZipReader* CreateFromMemory(const void* buffer, size_t size); diff -r f269e4778b59 -r b7243c4efe18 OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp --- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -2503,6 +2503,11 @@ DcmFileFormat* FromDcmtkBridge::LoadFromMemoryBuffer(const void* buffer, size_t size) { + if (!DicomMap::IsDicomFile(buffer, size)) + { + throw OrthancException(ErrorCode_BadFileFormat, "Not a DICOM file"); + } + DcmInputBufferStream is; if (size > 0) { diff -r f269e4778b59 -r b7243c4efe18 OrthancFramework/Sources/SystemToolbox.cpp --- a/OrthancFramework/Sources/SystemToolbox.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancFramework/Sources/SystemToolbox.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -266,7 +266,7 @@ } } - + // TODO-MEM: find a way to share code between these 2 overloads void SystemToolbox::ReadFile(MemoryManagedString& content, const boost::filesystem::path& path, bool log) diff -r f269e4778b59 -r b7243c4efe18 OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -177,14 +177,15 @@ Json::Value answer = Json::arrayValue; - std::string filename, content; + std::string filename; + MemoryManagedString content; while (reader->ReadNextFile(filename, content)) { if (!content.empty()) { LOG(INFO) << "Uploading DICOM file from ZIP archive: " << filename; - std::unique_ptr toStore(DicomInstanceToStore::CreateFromBuffer(content)); + std::unique_ptr toStore(DicomInstanceToStore::CreateFromBuffer(content.c_str(), content.size())); toStore->SetOrigin(DicomInstanceOrigin::FromRest(call)); try diff -r f269e4778b59 -r b7243c4efe18 OrthancServer/Sources/OrthancWebDav.cpp --- a/OrthancServer/Sources/OrthancWebDav.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancServer/Sources/OrthancWebDav.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -1213,7 +1213,7 @@ std::unique_ptr reader(ZipReader::CreateFromMemory(content)); std::string filename, uncompressedFile; - while (reader->ReadNextFile(filename, uncompressedFile)) + while (reader->ReadNextFile(filename, uncompressedFile)) // TODO-MEM: use MemoryManagedString { if (!uncompressedFile.empty()) { diff -r f269e4778b59 -r b7243c4efe18 OrthancServer/Sources/main.cpp --- a/OrthancServer/Sources/main.cpp Wed Mar 04 16:28:51 2026 +0100 +++ b/OrthancServer/Sources/main.cpp Thu Mar 05 15:40:24 2026 +0100 @@ -1949,7 +1949,9 @@ Logging::SetCurrentThreadName("MAIN"); SetGlobalVerbosity(Verbosity_Default); - LimitedMemoryAllocator::Initialize(8ul * 1024ul * 1024ul * 1024ul); // TODO-MEM: get this value from the configuration file + uint64_t maxMemorySize = 8ul * 1024ul * 1024ul * 1024ul; // TODO-MEM: get this value from the configuration file + maxMemorySize = std::min(maxMemorySize, std::numeric_limits::max()); // on 32 bits system, limit the value to 4GB + LimitedMemoryAllocator::Initialize(static_cast(maxMemorySize)); bool upgradeDatabase = false; bool loadJobsFromDatabase = true;