Skip to content

memory exhaustion in ReadDCMImage #533

Closed
@jgj212

Description

@jgj212

Version: ImageMagick 7.0.6-1 Q16 x86_64

$magick identify $FILE

When identify DCM file , imagemagick will allocate memory to store the data.

Here is the critical code:

              if (~length >= 1)
                data=(unsigned char *) AcquireQuantumMemory(length+1,quantum*       // line 3273
                  sizeof(*data));

length can be controlled as follow:

  int
    *bluemap,
    datum,       // line 3010
    *greenmap,
    *graymap,
    *redmap;

    ...

  size_t
    colors,
    height,
    length,
    number_scenes,
    quantum,      // line 3035
    status,
    width;

    ...

    datum=0;  // line 3179
    if (quantum == 4)
      {
        if (group == 0x0002)
          datum=ReadBlobLSBSignedLong(image);
        else
          datum=ReadBlobSignedLong(image);
      }
    else
      if (quantum == 2)
        {
          if (group == 0x0002)
            datum=ReadBlobLSBSignedShort(image);
          else
            datum=ReadBlobSignedShort(image);
        }
    quantum=0;
    length=1;    // line 3196
    if (datum != 0)
      {
        if ((strncmp(implicit_vr,"SS",2) == 0) ||
            (strncmp(implicit_vr,"US",2) == 0))
          quantum=2;
        else
          if ((strncmp(implicit_vr,"UL",2) == 0) ||
              (strncmp(implicit_vr,"SL",2) == 0) ||
              (strncmp(implicit_vr,"FL",2) == 0))
            quantum=4;
          else
            if (strncmp(implicit_vr,"FD",2) != 0)
              quantum=1;
            else
              quantum=8;
        if (datum != ~0)
          length=(size_t) datum/quantum;  // 3213, bomb
        else
          {
            /*
              Sequence and item of undefined length.
            */
            quantum=0;
            length=0;
          }
      }

datum is int which is 32bit and signed type, quantum is size_t which is 64bit and unsigned type.
datum is from file data, it is can be controlled, so can set datum value < 0.
quantum value is a constant as it just can be 1/2/4/8.

So if datum is a negative number, it will be convert to a unsigned 64bit which is very large in line 3213.
And the result "length" can be controlled as very large to cause memory exhaustion .

testcase:
https://github.com/jgj212/poc/blob/master/memory_exhaustion_in_ReadDCMImage

Credit: ADLab of Venustech

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions