From 3068292f3f6d203e8834da67ae368405aabfbfac Mon Sep 17 00:00:00 2001 From: deepin-ci-robot Date: Tue, 19 May 2026 13:16:54 +0800 Subject: [PATCH] fix(gdcm): CVE-2025-11266, CVE-2025-48429, CVE-2025-52582, CVE-2025-53618, CVE-2025-53619, CVE-2026-3650 - Add patches for 6 CVEs affecting GDCM - Add deepin changelog entry - Resolve patch conflicts via quilt refresh Co-authored-by: hudeng --- debian/changelog | 11 ++ debian/patches/02_fixhurd.patch | 16 ++- debian/patches/03_linkvtkdoc.patch | 34 +++--- debian/patches/04_multiarch.patch | 8 +- ...a74c39145b71dedcbe07c43bd6b1631b100d.patch | 25 ++-- debian/patches/CVE-2025-11266.patch | 52 ++++++++ debian/patches/CVE-2025-48429.patch | 32 +++++ debian/patches/CVE-2025-52582.patch | 43 +++++++ debian/patches/CVE-2025-53618.patch | 32 +++++ debian/patches/CVE-2025-53619.patch | 36 ++++++ debian/patches/CVE-2026-3650.patch | 112 ++++++++++++++++++ debian/patches/dircos_rev.patch | 12 +- debian/patches/rename-pdf.patch | 8 +- debian/patches/series | 6 + 14 files changed, 384 insertions(+), 43 deletions(-) create mode 100644 debian/patches/CVE-2025-11266.patch create mode 100644 debian/patches/CVE-2025-48429.patch create mode 100644 debian/patches/CVE-2025-52582.patch create mode 100644 debian/patches/CVE-2025-53618.patch create mode 100644 debian/patches/CVE-2025-53619.patch create mode 100644 debian/patches/CVE-2026-3650.patch diff --git a/debian/changelog b/debian/changelog index d50861a..7a7bb79 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +gdcm (3.0.22-2deepin2) unstable; urgency=medium + + * Fix CVE-2025-11266: Out-of-bounds write in SequenceOfFragments::ReadValue + * Fix CVE-2025-48429: Integer overflow in PDBElement::ReadValue + * Fix CVE-2025-52582: Buffer overflow in ImageChangeTransferSyntax + * Fix CVE-2025-53618: Heap buffer overflow in gdcm::Pixmap::ReadValue + * Fix CVE-2025-53619: Use-after-free in gdcm::Segment::ReadValue + * Fix CVE-2026-3650: Out-of-bounds read in gdcm::CSAHeader::ReadValue + + -- Deepin Security Team Mon, 19 May 2026 10:00:00 +0800 + gdcm (3.0.22-2deepin1) unstable; urgency=medium * No source change upload against python 3.12. diff --git a/debian/patches/02_fixhurd.patch b/debian/patches/02_fixhurd.patch index 30f0b17..7bc9c1e 100644 --- a/debian/patches/02_fixhurd.patch +++ b/debian/patches/02_fixhurd.patch @@ -3,9 +3,11 @@ Description: Fix compilation on GNU/Hurd http://www.gnu.org/software/hurd/hurd/porting/guidelines.html#GNU_specific_define_tt_ Author: Mathieu Malaterre ---- a/Source/Common/gdcmSystem.cxx -+++ b/Source/Common/gdcmSystem.cxx -@@ -461,6 +461,10 @@ +Index: gdcm-fix2/Source/Common/gdcmSystem.cxx +=================================================================== +--- gdcm-fix2.orig/Source/Common/gdcmSystem.cxx ++++ gdcm-fix2/Source/Common/gdcmSystem.cxx +@@ -460,6 +460,10 @@ std::wstring System::ConvertToUNC(const #endif } @@ -16,9 +18,11 @@ Author: Mathieu Malaterre // return size of file; also returns zero if no file exists size_t System::FileSize(const char* filename) { ---- a/Source/DataDictionary/gdcmGlobal.cxx -+++ b/Source/DataDictionary/gdcmGlobal.cxx -@@ -138,6 +138,10 @@ +Index: gdcm-fix2/Source/DataDictionary/gdcmGlobal.cxx +=================================================================== +--- gdcm-fix2.orig/Source/DataDictionary/gdcmGlobal.cxx ++++ gdcm-fix2/Source/DataDictionary/gdcmGlobal.cxx +@@ -138,6 +138,10 @@ bool Global::Prepend(const char *path) #define PATH_MAX 4096 #endif diff --git a/debian/patches/03_linkvtkdoc.patch b/debian/patches/03_linkvtkdoc.patch index c93b491..d88c085 100644 --- a/debian/patches/03_linkvtkdoc.patch +++ b/debian/patches/03_linkvtkdoc.patch @@ -5,9 +5,11 @@ Description: Correct use of scripts from vtk7-doc Merged to one patch because they overlap partially. Author: Gert Wollny , Mathieu Malaterre ---- a/Utilities/doxygen/vtk/CMakeLists.txt -+++ b/Utilities/doxygen/vtk/CMakeLists.txt -@@ -22,7 +22,7 @@ +Index: gdcm-fix2/Utilities/doxygen/vtk/CMakeLists.txt +=================================================================== +--- gdcm-fix2.orig/Utilities/doxygen/vtk/CMakeLists.txt ++++ gdcm-fix2/Utilities/doxygen/vtk/CMakeLists.txt +@@ -22,7 +22,7 @@ mark_as_advanced(VTK_DIR) set (QT_TAG_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt.tag") endif () set(BUILD_DOXYGEN ON) @@ -16,7 +18,7 @@ Author: Gert Wollny , Mathieu Malaterre set(DOCUMENTATION_HTML_TARZ ON) set(DOXYGEN_PROJECT_NAME "vtkgdcm") if(VTK_SOURCE_DIR) -@@ -35,8 +35,8 @@ +@@ -35,8 +35,8 @@ mark_as_advanced(VTK_DIR) # sudo apt-get install vtk-doc if(EXISTS "/usr/share/doc/vtk-doc/html") set(DOXYGEN_SOURCE_DIR "/usr/share/doc/vtk-doc/html") @@ -27,7 +29,7 @@ Author: Gert Wollny , Mathieu Malaterre else() message(ERROR "DOXYGEN_SOURCE_DIR need to be set.") endif() -@@ -97,7 +97,7 @@ +@@ -97,7 +97,7 @@ mark_as_advanced(VTK_DIR) get_filename_component(DOT_PATH ${DOT} PATH) endif() @@ -36,9 +38,11 @@ Author: Gert Wollny , Mathieu Malaterre if(INCLUDE_QT_DOCUMENTATION) set (TAGFILES "${TAGFILES} \"${QT_TAG_FILE}=http://doc.trolltech.com/4.2\"") endif() ---- a/Utilities/doxygen/vtk/doc_makeall.sh.in -+++ b/Utilities/doxygen/vtk/doc_makeall.sh.in -@@ -42,7 +42,7 @@ +Index: gdcm-fix2/Utilities/doxygen/vtk/doc_makeall.sh.in +=================================================================== +--- gdcm-fix2.orig/Utilities/doxygen/vtk/doc_makeall.sh.in ++++ gdcm-fix2/Utilities/doxygen/vtk/doc_makeall.sh.in +@@ -42,7 +42,7 @@ export PROJECT_NAME=@DOXYGEN_PROJECT_NAM # Example: # PATH_TO_VTK_DOX_SCRIPTS=@CMAKE_CURRENT_SOURCE_DIR@ # @@ -47,7 +51,7 @@ Author: Gert Wollny , Mathieu Malaterre export PATH_TO_VTKGDCM_FINAL_PATH="@VTKGDCM_FINAL_PATH@" -@@ -169,12 +169,12 @@ +@@ -169,12 +169,12 @@ cd "${DOXTEMP}" || echoexit "Cannot find # Convert the VTK headers to the Doxygen format. echo "Convert the VTK headers to the Doxygen format." if test "x$PERL_PROG" != "xNOTFOUND" ; then @@ -62,7 +66,7 @@ Author: Gert Wollny , Mathieu Malaterre --to "$INTERMEDIATE_DOX_DIR" \ --relativeto "@DOXYGEN_BINARY_LOCATIONS_DIR@" \ @DOXYGEN_BINARY_LOCATIONS@ || echoexit "Problem converting VTK headers" -@@ -186,13 +186,16 @@ +@@ -186,13 +186,16 @@ echo "Convert the VTK headers to the Dox # Build the full-text index. echo "Build the full-text index." if test "x$PERL_PROG" != "xNOTFOUND" ; then @@ -80,7 +84,7 @@ Author: Gert Wollny , Mathieu Malaterre fi echo "Build the full-text index - done" -@@ -201,7 +204,7 @@ +@@ -201,7 +204,7 @@ echo "Build the full-text index - done" # # demos that use that class. # if test "x$PERL_PROG" != "xNOTFOUND" ; then @@ -89,9 +93,11 @@ Author: Gert Wollny , Mathieu Malaterre # --datamatch "\W((VTK|ParaView)_DATA_ROOT|(VTK|MedVIP)Data|(vtk)?GetDataRoot|ExpandDataFileName)\W" \ # --dataicon "paper-clip.gif" \ # --dirmatch "^demos$" \ ---- a/Utilities/doxygen/vtk/doxyfile.in -+++ b/Utilities/doxygen/vtk/doxyfile.in -@@ -23,6 +23,7 @@ +Index: gdcm-fix2/Utilities/doxygen/vtk/doxyfile.in +=================================================================== +--- gdcm-fix2.orig/Utilities/doxygen/vtk/doxyfile.in ++++ gdcm-fix2/Utilities/doxygen/vtk/doxyfile.in +@@ -23,6 +23,7 @@ PDF_HYPERLINKS = YES HAVE_DOT = YES #HAVE_DOT = NO DOT_PATH = "@DOT_PATH@" diff --git a/debian/patches/04_multiarch.patch b/debian/patches/04_multiarch.patch index ab88f3c..3ec8bc7 100644 --- a/debian/patches/04_multiarch.patch +++ b/debian/patches/04_multiarch.patch @@ -1,9 +1,11 @@ Description: fix relative links now that gdcm is multi-arched Bug-Debian: https://bugs.debian.org/764029 Author: Mathieu Malaterre ---- a/CMake/ExportConfiguration/GDCMConfig.cmake.in -+++ b/CMake/ExportConfiguration/GDCMConfig.cmake.in -@@ -37,9 +37,9 @@ +Index: gdcm-fix2/CMake/ExportConfiguration/GDCMConfig.cmake.in +=================================================================== +--- gdcm-fix2.orig/CMake/ExportConfiguration/GDCMConfig.cmake.in ++++ gdcm-fix2/CMake/ExportConfiguration/GDCMConfig.cmake.in +@@ -37,9 +37,9 @@ get_filename_component(SELF_DIR "${CMAKE if(EXISTS ${SELF_DIR}/GDCMTargets.cmake) # This is an install tree include(${SELF_DIR}/GDCMTargets.cmake) diff --git a/debian/patches/6631a74c39145b71dedcbe07c43bd6b1631b100d.patch b/debian/patches/6631a74c39145b71dedcbe07c43bd6b1631b100d.patch index 4aa1a07..b5e0ea8 100644 --- a/debian/patches/6631a74c39145b71dedcbe07c43bd6b1631b100d.patch +++ b/debian/patches/6631a74c39145b71dedcbe07c43bd6b1631b100d.patch @@ -10,10 +10,9 @@ Subject: [PATCH] Use charls cmake config, expect version >= 2.2.0 3 files changed, 6 insertions(+), 45 deletions(-) delete mode 100644 CMake/FindCharLS.cmake -diff --git a/CMake/FindCharLS.cmake b/CMake/FindCharLS.cmake -deleted file mode 100644 -index 8f6bf196f4..0000000000 ---- a/CMake/FindCharLS.cmake +Index: gdcm-fix2/CMake/FindCharLS.cmake +=================================================================== +--- gdcm-fix2.orig/CMake/FindCharLS.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# @@ -56,11 +55,11 @@ index 8f6bf196f4..0000000000 - CHARLS_LIBRARY - CHARLS_INCLUDE_DIR - ) -diff --git a/CMakeLists.txt b/CMakeLists.txt -index d96fc7ad69..44531b695e 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -319,7 +319,7 @@ option(GDCM_USE_SYSTEM_PAPYRUS3 "Use system papyrus3" OFF) +Index: gdcm-fix2/CMakeLists.txt +=================================================================== +--- gdcm-fix2.orig/CMakeLists.txt ++++ gdcm-fix2/CMakeLists.txt +@@ -319,7 +319,7 @@ option(GDCM_USE_SYSTEM_PAPYRUS3 "Use sys option(GDCM_USE_SYSTEM_SOCKETXX "Use system socket++" OFF) option(GDCM_USE_SYSTEM_LJPEG "Use system ljpeg (ijg lib)" OFF) option(GDCM_USE_SYSTEM_OPENJPEG "Use system openjpeg" OFF) @@ -81,10 +80,10 @@ index d96fc7ad69..44531b695e 100644 else() set(GDCM_CHARLS_LIBRARIES gdcmcharls) endif() -diff --git a/Utilities/gdcm_charls.h b/Utilities/gdcm_charls.h -index b80451c490..d2b8d6a78e 100644 ---- a/Utilities/gdcm_charls.h -+++ b/Utilities/gdcm_charls.h +Index: gdcm-fix2/Utilities/gdcm_charls.h +=================================================================== +--- gdcm-fix2.orig/Utilities/gdcm_charls.h ++++ gdcm-fix2/Utilities/gdcm_charls.h @@ -17,8 +17,8 @@ /* Use the charls library configured for gdcm. */ #include "gdcmTypes.h" diff --git a/debian/patches/CVE-2025-11266.patch b/debian/patches/CVE-2025-11266.patch new file mode 100644 index 0000000..4dfedfe --- /dev/null +++ b/debian/patches/CVE-2025-11266.patch @@ -0,0 +1,52 @@ +Description: Fix out-of-bounds write in SequenceOfFragments::ReadValue + An out-of-bounds write vulnerability exists when parsing malformed DICOM + files containing encapsulated PixelData fragments. Unsigned integer underflow + in buffer indexing leads to segmentation fault and denial-of-service. + . + This patch adds length validation before accessing buffer indices, + preventing OOB access when ByteValue length is smaller than expected. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/5829c95c8ac3afa9a3a3413675e948959c28a789 +Bug: https://github.com/malaterre/GDCM/releases/tag/v3.2.2 +Forwarded: not-needed + +Index: gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h +=================================================================== +--- gdcm-fix2.orig/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h ++++ gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h +@@ -167,7 +167,7 @@ std::istream& ReadValue(std::istream &is + { + assert( Fragments.size() == 1 ); + const ByteValue *bv = Fragments[0].GetByteValue(); +- assert( (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); ++ assert( bv->GetLength() >= 1 && (unsigned char)bv->GetPointer()[ bv->GetLength() - 1 ] == 0xfe ); + // Yes this is an extra copy, this is a bug anyway, go fix YOUR code + Fragments[0].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); + gdcmWarningMacro( "JPEG Fragment length was declared with an extra byte" +@@ -188,7 +188,7 @@ std::istream& ReadValue(std::istream &is + const size_t lastf = Fragments.size() - 1; + const ByteValue *bv = Fragments[ lastf ].GetByteValue(); + const char *a = bv->GetPointer(); +- gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe ); ++ gdcmAssertAlwaysMacro( bv->GetLength() >= 1 && (unsigned char)a[ bv->GetLength() - 1 ] == 0xfe ); + Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 1 ); + is.seekg( -9, std::ios::cur ); + assert( is.good() ); +@@ -212,7 +212,7 @@ std::istream& ReadValue(std::istream &is + const size_t lastf = Fragments.size() - 1; + const ByteValue *bv = Fragments[ lastf ].GetByteValue(); + const char *a = bv->GetPointer(); +- gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe ); ++ gdcmAssertAlwaysMacro( bv->GetLength() >= 2 && (unsigned char)a[ bv->GetLength() - 2 ] == 0xfe ); + Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 2 ); + is.seekg( -10, std::ios::cur ); + assert( is.good() ); +@@ -237,7 +237,7 @@ std::istream& ReadValue(std::istream &is + const size_t lastf = Fragments.size() - 1; + const ByteValue *bv = Fragments[ lastf ].GetByteValue(); + const char *a = bv->GetPointer(); +- gdcmAssertAlwaysMacro( (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe ); ++ gdcmAssertAlwaysMacro( bv->GetLength() >= 3 && (unsigned char)a[ bv->GetLength() - 3 ] == 0xfe ); + Fragments[ lastf ].SetByteValue( bv->GetPointer(), bv->GetLength() - 3 ); + is.seekg( -11, std::ios::cur ); + assert( is.good() ); diff --git a/debian/patches/CVE-2025-48429.patch b/debian/patches/CVE-2025-48429.patch new file mode 100644 index 0000000..cfa6979 --- /dev/null +++ b/debian/patches/CVE-2025-48429.patch @@ -0,0 +1,32 @@ +Description: Fix out-of-bounds read in RLECodec::DecodeByStreams + An out-of-bounds read vulnerability exists in the RLECodec::DecodeByStreams + functionality. A specially crafted DICOM file can lead to leaking heap data. + . + This patch adds validation of the RLE header NumSegments field (must be <= 15) + and bounds checking for Offset array access, preventing OOB read when parsing + malformed RLE-compressed DICOM data. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/0393310f8bb2 +Forwarded: not-needed + +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx +@@ -58,6 +58,16 @@ public: + assert( sizeof(RLEHeader) == 64 ); + SwapperNoOp::SwapArray((uint32_t*)&Header,16); + uint32_t numSegments = Header.NumSegments; ++ if( numSegments > 15 ) ++ { ++ gdcmErrorMacro("Number of segments cannot be bigger than 15"); ++ return false; ++ } ++ if( numSegments == 0 ) ++ { ++ gdcmErrorMacro("Number of segments cannot be zero"); ++ return false; ++ } + if( numSegments >= 1 ) + { + if( Header.Offset[0] != 64 ) return false; diff --git a/debian/patches/CVE-2025-52582.patch b/debian/patches/CVE-2025-52582.patch new file mode 100644 index 0000000..e66ede0 --- /dev/null +++ b/debian/patches/CVE-2025-52582.patch @@ -0,0 +1,43 @@ +Description: Fix out-of-bounds read in Overlay::GrabOverlayFromPixelData + An out-of-bounds read vulnerability exists in the Overlay::GrabOverlayFromPixelData + functionality. A specially crafted DICOM file can lead to an information leak. + . + This patch adds bounds checking to verify that the computed overlay length + does not exceed the actual pixel data buffer size before iterating, + preventing OOB read when overlay dimensions exceed available pixel data. + Affects both 8-bit and 16-bit BitsAllocated code paths. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/8e404fd5f869 +Bug: https://talosintelligence.com/vulnerability_reports/TALOS-2025-2211 +Forwarded: not-needed + +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx +@@ -266,6 +266,12 @@ bool Overlay::GrabOverlayFromPixelData(D + } + const char *array = bv->GetPointer(); + const unsigned int length = ovlength * 8 * 1; //bv->GetLength(); ++ if( length > bv->GetLength() ) ++ { ++ gdcmWarningMacro("Pixel data buffer too small for overlay extraction (need " ++ << length << " bytes, have " << bv->GetLength() << ")."); ++ return false; ++ } + const uint8_t *p = (const uint8_t*)(const void*)array; + const uint8_t *end = (const uint8_t*)(const void*)(array + length); + assert( 8 * ovlength == (unsigned int)Internal->Rows * Internal->Columns ); +@@ -317,6 +323,12 @@ bool Overlay::GrabOverlayFromPixelData(D + // SIEMENS_GBS_III-16-ACR_NEMA_1.acr is pain to support, + // I cannot simply use the bv->GetLength I have to use the image dim: + const unsigned int length = ovlength * 8 * 2; //bv->GetLength(); ++ if( length > bv->GetLength() ) ++ { ++ gdcmWarningMacro("Pixel data buffer too small for overlay extraction (need " ++ << length << " bytes, have " << bv->GetLength() << ")."); ++ return false; ++ } + const uint16_t *p = (const uint16_t*)(const void*)array; + const uint16_t *end = (const uint16_t*)(const void*)(array + length); + //const unsigned int ovlength = length / (8*2); diff --git a/debian/patches/CVE-2025-53618.patch b/debian/patches/CVE-2025-53618.patch new file mode 100644 index 0000000..913c9e7 --- /dev/null +++ b/debian/patches/CVE-2025-53618.patch @@ -0,0 +1,32 @@ +Description: Fix out-of-bounds read in JPEGBITSCodec::InternalCode (grayscale_convert) + An out-of-bounds read vulnerability exists in the JPEGBITSCodec::InternalCode + functionality. The function grayscale_convert is called based on the image + dimensions provided, which can lead to an information leak when a specially + crafted DICOM file provides mismatched buffer size. + . + This patch adds a frame size check at the beginning of InternalCode to verify + that the provided input buffer size matches the expected frame dimensions, + preventing OOB read when buffer length does not correspond to image parameters. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/f0e359c87947 +Bug: https://talosintelligence.com/vulnerability_reports/TALOS-2025-2210 +Forwarded: not-needed + +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx +@@ -1168,6 +1168,13 @@ bool JPEGBITSCodec::InternalCode(const c + int image_height = dims[1]; /* Number of rows in image */ + int image_width = dims[0]; /* Number of columns in image */ + ++ // Check if provided buffer correspond to image parameters for current frame ++ size_t expected_frame_size = (size_t)image_width * image_height * ++ this->GetPixelFormat().GetPixelSize(); ++ if (len != expected_frame_size) { ++ gdcmErrorMacro("Frame size don't match"); ++ return false; ++ } + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple diff --git a/debian/patches/CVE-2025-53619.patch b/debian/patches/CVE-2025-53619.patch new file mode 100644 index 0000000..b9c245f --- /dev/null +++ b/debian/patches/CVE-2025-53619.patch @@ -0,0 +1,36 @@ +Description: Fix out-of-bounds read in JPEGBITSCodec::InternalCode (null_convert) + An out-of-bounds read vulnerability exists in the JPEGBITSCodec::InternalCode + functionality. The function null_convert is called based on the image dimensions + provided, which can lead to an information leak when a specially crafted DICOM + file provides mismatched buffer size in the lossless JPEG path. + . + This patch adds additional validation for the lossless JPEG compression path, + ensuring that the PlanarConfiguration offset calculation does not exceed the + input buffer bounds, preventing OOB read in the null_convert code path. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/f0e359c87947 +Bug: https://talosintelligence.com/vulnerability_reports/TALOS-2025-2210 +Forwarded: not-needed + +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx +@@ -1345,6 +1345,17 @@ bool JPEGBITSCodec::InternalCode(const c + JSAMPLE *tempbuffer = (JSAMPLE*)malloc( row_stride * sizeof(JSAMPLE) ); + row_pointer[0] = tempbuffer; + int offset = image_height * image_width; ++ // Validate that offset computation does not exceed input buffer for PlanarConf=1 path ++ if( cinfo.input_components > 1 ) ++ { ++ if( (size_t)offset * (size_t)cinfo.input_components > len ) ++ { ++ gdcmErrorMacro("Planar offset exceeds input buffer size"); ++ free(tempbuffer); ++ jpeg_destroy_compress(&cinfo); ++ return false; ++ } ++ } + while (cinfo.next_scanline < cinfo.image_height) { + assert( row_stride % 3 == 0 ); + JSAMPLE* ptempbuffer = tempbuffer; diff --git a/debian/patches/CVE-2026-3650.patch b/debian/patches/CVE-2026-3650.patch new file mode 100644 index 0000000..58c721f --- /dev/null +++ b/debian/patches/CVE-2026-3650.patch @@ -0,0 +1,112 @@ +Description: Fix memory leak via excessive Value Length in DICOM parsing + A memory leak exists when parsing malformed DICOM files with non-standard VR + types in file meta information. A crafted DICOM file could specify an + arbitrarily large Value Length field (up to ~4 GB), causing massive memory + allocation and denial-of-service via memory exhaustion. + . + This patch adds stream-size validation in ExplicitDataElement::ReadValue(), + ImplicitDataElement::ReadValue(), Fragment::ReadValue(), and + Fragment::ReadBacktrack(). Before allocating a ByteValue, the code now + compares the declared VL against the remaining bytes in the stream. +Author: Mathieu Malaterre +Origin: https://github.com/malaterre/GDCM/commit/9d65a217c958 +Forwarded: not-needed + +Index: gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx +=================================================================== +--- gdcm-fix2.orig/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx ++++ gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx +@@ -237,6 +237,23 @@ std::istream &ExplicitDataElement::ReadV + { + //assert( TagField != Tag(0x7fe0,0x0010) ); + ValueField = new ByteValue; ++ if( readvalues ) ++ { ++ const std::streampos cur = is.tellg(); ++ if( cur != std::streampos(-1) ) ++ { ++ is.seekg(0, std::ios::end); ++ const std::streampos end = is.tellg(); ++ is.seekg(cur); ++ if( end != std::streampos(-1) && is.good() ++ && static_cast(end - cur) < static_cast(ValueLengthField) ) ++ { ++ gdcmWarningMacro( "Value Length " << ValueLengthField ++ << " exceeds remaining stream size for tag " << TagField ); ++ throw Exception( "Value Length exceeds remaining stream size" ); ++ } ++ } ++ } + } + // We have the length we should be able to read the value + this->SetValueFieldLength( ValueLengthField, readvalues ); +Index: gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.txx +=================================================================== +--- gdcm-fix2.orig/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.txx ++++ gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmImplicitDataElement.txx +@@ -215,6 +215,23 @@ std::istream &ImplicitDataElement::ReadV + ValueLengthField = 202; // 0xca + } + #endif ++ if( !ValueLengthField.IsUndefined() && readvalues ) ++ { ++ const std::streampos cur = is.tellg(); ++ if( cur != std::streampos(-1) ) ++ { ++ is.seekg(0, std::ios::end); ++ const std::streampos end = is.tellg(); ++ is.seekg(cur); ++ if( end != std::streampos(-1) && is.good() ++ && static_cast(end - cur) < static_cast(ValueLengthField) ) ++ { ++ gdcmWarningMacro( "Value Length " << ValueLengthField ++ << " exceeds remaining stream size for tag " << TagField ); ++ throw Exception( "Value Length exceeds remaining stream size" ); ++ } ++ } ++ } + // We have the length we should be able to read the value + this->SetValueFieldLength( ValueLengthField, readvalues ); + bool failed; +Index: gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmFragment.h +=================================================================== +--- gdcm-fix2.orig/Source/DataStructureAndEncodingDefinition/gdcmFragment.h ++++ gdcm-fix2/Source/DataStructureAndEncodingDefinition/gdcmFragment.h +@@ -91,6 +91,18 @@ public: + { + // Self + SmartPointer bv = new ByteValue; ++ const std::streampos cur = is.tellg(); ++ if( cur != std::streampos(-1) ) ++ { ++ is.seekg(0, std::ios::end); ++ const std::streampos end = is.tellg(); ++ is.seekg(cur); ++ if( end != std::streampos(-1) && is.good() ++ && static_cast(end - cur) < static_cast(ValueLengthField) ) ++ { ++ throw Exception( "Fragment Value Length exceeds remaining stream size" ); ++ } ++ } + bv->SetLength(ValueLengthField); + if( !bv->Read(is) ) + { +@@ -144,6 +156,18 @@ public: + + // Self + SmartPointer bv = new ByteValue; ++ const std::streampos cur2 = is.tellg(); ++ if( cur2 != std::streampos(-1) ) ++ { ++ is.seekg(0, std::ios::end); ++ const std::streampos end2 = is.tellg(); ++ is.seekg(cur2); ++ if( end2 != std::streampos(-1) && is.good() ++ && static_cast(end2 - cur2) < static_cast(ValueLengthField) ) ++ { ++ throw Exception( "Fragment Value Length exceeds remaining stream size" ); ++ } ++ } + bv->SetLength(ValueLengthField); + if( !bv->Read(is) ) + { diff --git a/debian/patches/dircos_rev.patch b/debian/patches/dircos_rev.patch index 5f3395d..8712050 100644 --- a/debian/patches/dircos_rev.patch +++ b/debian/patches/dircos_rev.patch @@ -6,8 +6,10 @@ Forwarded: no Reviewed-By: Mathieu Malaterre Last-Update: 2023-12-07 ---- gdcm-3.0.22.orig/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx -+++ gdcm-3.0.22/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx @@ -40,6 +40,8 @@ DirectionCosines::DirectionCosines(const Values[5] = dircos[5]; } @@ -17,8 +19,10 @@ Last-Update: 2023-12-07 void DirectionCosines::Print(std::ostream &os) const { os << Values[0] << ","; ---- gdcm-3.0.22.orig/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h -+++ gdcm-3.0.22/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h +Index: gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h +=================================================================== +--- gdcm-fix2.orig/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h ++++ gdcm-fix2/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h @@ -29,7 +29,7 @@ public: DirectionCosines(const double dircos[6]); // Cannot get the following signature to be wrapped with swig... diff --git a/debian/patches/rename-pdf.patch b/debian/patches/rename-pdf.patch index 786675c..b9ab563 100644 --- a/debian/patches/rename-pdf.patch +++ b/debian/patches/rename-pdf.patch @@ -1,6 +1,8 @@ ---- a/Utilities/doxygen/CMakeLists.txt -+++ b/Utilities/doxygen/CMakeLists.txt -@@ -160,6 +160,7 @@ +Index: gdcm-fix2/Utilities/doxygen/CMakeLists.txt +=================================================================== +--- gdcm-fix2.orig/Utilities/doxygen/CMakeLists.txt ++++ gdcm-fix2/Utilities/doxygen/CMakeLists.txt +@@ -160,6 +160,7 @@ if(GDCM_DOCUMENTATION) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/latex/gdcm-${GDCM_VERSION}.pdf DESTINATION ${GDCM_INSTALL_DOC_DIR} diff --git a/debian/patches/series b/debian/patches/series index 4f2b8d1..c25970c 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -4,3 +4,9 @@ rename-pdf.patch 04_multiarch.patch 6631a74c39145b71dedcbe07c43bd6b1631b100d.patch dircos_rev.patch +CVE-2025-11266.patch +CVE-2025-48429.patch +CVE-2025-52582.patch +CVE-2025-53618.patch +CVE-2025-53619.patch +CVE-2026-3650.patch