Menu

#575 CVE-2025-52582

3.0.25
open
None
5
2026-05-29
2026-01-09
No

This description is extracted from https://talosintelligence.com/vulnerability_reports/TALOS-2025-2211

LINE 1. bool Overlay::GrabOverlayFromPixelData(DataSet const &ds)
LINE 2. {
LINE 3.   const unsigned int ovlength = Internal->Rows * Internal->Columns / 8;
LINE 4.   Internal->Data.resize( ovlength ); // set to 0
LINE 5.   if( Internal->BitsAllocated == 8 )
LINE 6.     {
LINE 7.     if( !ds.FindDataElement( Tag(0x7fe0,0x0010) ) )
LINE 8.       {
LINE 9.       gdcmWarningMacro("Could not find Pixel Data. Cannot extract Overlay." );
LINE 10.       return false;
LINE 11.       }
LINE 12.     const DataElement &pixeldata = ds.GetDataElement( Tag(0x7fe0,0x0010) );
LINE 13.     const ByteValue *bv = pixeldata.GetByteValue();
LINE 14.     if( !bv )
LINE 15.       {
LINE 16.       gdcmWarningMacro("Could not extract overlay from encapsulated stream." );
LINE 17.       return false;
LINE 18.       }
LINE 19.     const char *array = bv->GetPointer();
LINE 20.     const unsigned int length = ovlength * 8 * 1; //bv->GetLength();
LINE 21.     const uint8_t *p = (const uint8_t*)(const void*)array;
LINE 22.     const uint8_t *end = (const uint8_t*)(const void*)(array + length);
LINE 23.     assert( 8 * ovlength == (unsigned int)Internal->Rows * Internal->Columns );
LINE 24.     if( Internal->Data.empty() )
LINE 25.       {
LINE 26.       gdcmWarningMacro("Internal Data is empty." );
LINE 27.       return false;
LINE 28.       }
LINE 29.     unsigned char * overlay = (unsigned char*)Internal->Data.data();
LINE 30.     int c = 0;
LINE 31.     uint8_t pmask = (uint8_t)(1 << Internal->BitPosition);
LINE 32.     assert( length / 1 == ovlength * 8 );
LINE 33.     while( p != end )
LINE 34.       {
LINE 35.       const uint8_t val = *p & pmask; 
LINE 36.       assert( val == 0x0 || val == pmask );
LINE 37.       // 128 -> 0x80
LINE 38.       if( val )
LINE 39.         {
LINE 40.         overlay[ c / 8 ] |= (unsigned char)(0x1 << c%8);
LINE 41.         }
LINE 42.       else
LINE 43.         {
LINE 44.         // else overlay[ c / 8 ] is already 0
LINE 45.         }
LINE 46.       ++p;
LINE 47.       ++c;
LINE 48.       }
LINE 49.     assert( (unsigned)c / 8 == ovlength );
LINE 50.     }
   [...]
LINE 109. }

The end pointer is computed LINE 22 to the value of the (array + length) where length come from the result of ovlength * 8 * 1 at LINE 29 and array LINE 19 The array is pointer to bytes read from file in memory, which is given the same value to p LINE 21. array obtained from the call to bv->GetPointer() where bv is a ByteValue * LINE 13 is the corresponding data to the pixeldata DICOM record, a Tag(0x7fe0,0x0010) at LINE12 The length of this array is bv->GetLength() corresponding to the size stored into the DICOM pixeldata DICOM record Tag(0x7fe0,0x0010)

The ovlengthis computed with Internal->Rows * Internal->Columns / 8 LINE 3 The issue is happening when length is bigger than the real size of the memory of end pointer causing an out-of-bounds read of memory pointed by p. The malformed file is enabling to control the length and the real size of p enabling the control of the while-loop LINE 33 leading potentially to infoleaks. By the way GLIBC contains a lot of sensitives info which can be used later for exploitation.

The crash occurs due to an out-of-bounds read triggered when the end pointer is calculated incorrectly. The issue arises as follows: - At LINE 22, the end pointer is computed as (array + length), where length is determined from the expression ovlength * 8 * 1 at LINE 29. - The array pointer, initialized at LINE 19, points to bytes read from the file into memory. It is also assigned to p at LINE 21. - The array is obtained from the call to bv->GetPointer(), where bv is a ByteValue* at LINE 13. This corresponds to the data in the pixeldata DICOM record, identified by the Tag (0x7fe0, 0x0010) at LINE 12. - The real size of this array could be determined by bv->GetLength(), which represents the size of the DICOM PixelData record stored in the Tag (0x7fe0, 0x0010).

The calculation of ovlength is done at LINE 3 as Internal->Rows * Internal->Columns / 8. However, the issue occurs when the length value exceeds the actual size of the memory allocated to the array. This causes the end pointer to point beyond the valid memory range. As a result, the while loop at LINE 33 iterates over invalid memory, leading to an out-of-bounds read from the p pointer. The malformed DICOM file manipulates the length and the actual size of p to control the loop behavior, potentially leaking sensitive information.

Given that GLIBC contains a wealth of sensitive data, such as function pointers and memory layouts, this vulnerability could be exploited further for information leaks or other malicious purposes.

Discussion

  • Emmanuel Arias

    Emmanuel Arias - 2026-05-13

    Hello!

    I'm from Debian LTS team. I'd like to know if you have news about this fix?

    Thanks

     
  • Emmanuel Arias

    Emmanuel Arias - 2026-05-28

    Hello!

    Sorry for bother you, do you have any updates here?

    Thanks

     

Log in to post a comment.