Repository: opencv
Issue: Integer overflow in cvInitImageHeader leading to incorrectly sized imageData allocation and likely causing vulnerabilities in code using this API
Labels: RFC

In OpenCV you can create an image with cvCreateImage, passing a size, number of channels and depth. Internally OpenCV calls cvInitImageHeader to initialise the IplImage structure. When it does this there is an integer overflow when calculating widthStep. This leads to imageSize being calculated incorrectly and ultimately cvCreateData calling cvAlloc with the incorrect imageSize. If the code using this API checks the imageSize field of the IplImage struct appropriately then it could avoid any vulnerability, however if the code blindly assumes that there has been enough space allocated for imageData based on the parameters passed to cvCreateImage (which is a reasonable assumption) then it could ultimately lead to out of bounds memory read/write.

The code can be found in modules/core/src/array.cpp
```c
CV_IMPL IplImage*
cvInitImageHeader( IplImage * image, CvSize size, int depth,
                   int channels, int origin, int align )
{    
    [...]
    image->nChannels = MAX( channels, 1 );
    image->depth = depth;
    image->align = align;
    image->widthStep = (((image->width * image->nChannels *
         (image->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ align - 1) & (~(align - 1));
    image->origin = origin;
    const int64 imageSize_tmp = (int64)image->widthStep*(int64)image->height;
    image->imageSize = (int)imageSize_tmp;
    if( (int64)image->imageSize != imageSize_tmp )
        CV_Error( CV_StsNoMem, "Overflow for imageSize" );

    return image;
}
```

Although the imageSize is checked for overflow, widthStep is not checked for overflow, which is the thing that actually overflows.
After this, imageData is initialised in cvCreateData:

```c
CV_IMPL void
cvCreateData( CvArr* arr )
{
    [...]
        if( !CvIPL.allocateData )
        {
            const int64 imageSize_tmp = (int64)img->widthStep*(int64)img->height;
            if( (int64)img->imageSize != imageSize_tmp )
                CV_Error( CV_StsNoMem, "Overflow for imageSize" );
            img->imageData = img->imageDataOrigin =
                        (char*)cvAlloc( (size_t)img->imageSize );
        }
    [...]
}
```

This bug still exists in the latest version of OpenCV and appears to have been there for at least the last 9 years. This bug will very likely lead to a security vulnerability wherever some code uses this API and assumes that there has been sufficient space allocated for the image. There may also be some code internal to OpenCV which makes the same assumption about the allocation size from width and height etc. and doesn't explicitly check imageSize thus leading to an exploitable vulnerability within the OpenCV code.


This bug could be triggered with a piece of code like:
```c
int width = 0x1fffffff;
int height = 2;
int channels = 3;
int depth = 8;
IplImage *im = cvCreateImage(cvSize(width, height), depth, channels);

// This is writing beyond the end of the imageData buffer which it shouldn't be
im->imageData[0x40000010] = 1;
```