Skip to content
Permalink
Browse files

[server] Check image size for overflow and throw if null

Because we don't wont a broken image in the output
when a null image is created.

This introduces an additional check for null images
and a check for image size taken verbatim from QImage
internal checks.

This fixes an unreported bug that produced a broken image
instead of a proper exception in case of size overflow
due to QImage internal checks or to out of memory conditions.
  • Loading branch information
elpaso committed Jan 17, 2018
1 parent 4fc2b3e commit 74d76d52a7f2ddb8c6a6d7404e48f421302108fe
Showing with 36 additions and 4 deletions.
  1. +36 −4 src/server/services/wms/qgswmsrenderer.cpp
@@ -1041,23 +1041,29 @@ namespace QgsWms
throw QgsException( QStringLiteral( "createImage: Invalid width / height parameters" ) );
}

QImage *image = nullptr;
std::unique_ptr<QImage> image;

// use alpha channel only if necessary because it slows down performance
QgsWmsParameters::Format format = mWmsParameters.format();
bool transparent = mWmsParameters.transparentAsBool();

if ( transparent && format != QgsWmsParameters::JPG )
{
image = new QImage( width, height, QImage::Format_ARGB32_Premultiplied );
image = qgis::make_unique<QImage>( width, height, QImage::Format_ARGB32_Premultiplied );
image->fill( 0 );
}
else
{
image = new QImage( width, height, QImage::Format_RGB32 );
image = qgis::make_unique<QImage>( width, height, QImage::Format_RGB32 );
image->fill( mWmsParameters.backgroundColorAsColor() );
}

// Check that image was correctly created
if ( image->isNull() )
{
throw QgsException( QStringLiteral( "createImage: image could not be created, check for out of memory conditions" ) );
}

//apply DPI parameter if present. This is an extension of Qgis Mapserver compared to WMS 1.3.
//Because of backwards compatibility, this parameter is optional
double OGC_PX_M = 0.00028; // OGC reference pixel size in meter, also used by qgis
@@ -1067,7 +1073,7 @@ namespace QgsWms

image->setDotsPerMeterX( dpm );
image->setDotsPerMeterY( dpm );
return image;
return image.release();
}

void QgsRenderer::configureMapSettings( const QPaintDevice *paintDevice, QgsMapSettings &mapSettings ) const
@@ -1830,6 +1836,32 @@ namespace QgsWms
return false;
}

// Sanity check from internal QImage checks (see qimage.cpp)
// this is to report a meaningful error message in case of
// image creation failure and to differentiate it from out
// of memory conditions.

// depth for now it cannot be anything other than 32, but I don't like
// to hardcode it: I hope we will support other depths in the future.
uint depth = 32;
switch ( mWmsParameters.format() )
{
case QgsWmsParameters::Format::JPG:
case QgsWmsParameters::Format::PNG:
default:
depth = 32;
}

const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2; // bytes per scanline (must be multiple of 4)

if ( INT_MAX / depth < width
|| bytes_per_line <= 0
|| height <= 0
|| INT_MAX / uint( bytes_per_line ) < height
|| INT_MAX / sizeof( uchar * ) < uint( height ) )
return false;


return true;
}

0 comments on commit 74d76d5

Please sign in to comment.
You can’t perform that action at this time.