Skip to content

Commit

Permalink
Merge pull request #6089 from elpaso/server-exception-on-image-overflow
Browse files Browse the repository at this point in the history
Server exception on image overflow
  • Loading branch information
elpaso committed Jan 17, 2018
2 parents ccd98f5 + bdb5727 commit 479358e
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
39 changes: 35 additions & 4 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -1830,6 +1836,31 @@ 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 ( std::numeric_limits<int>::max() / depth < ( uint )width
|| bytes_per_line <= 0
|| height <= 0
|| std::numeric_limits<int>::max() / uint( bytes_per_line ) < ( uint )height
|| std::numeric_limits<int>::max() / sizeof( uchar * ) < uint( height ) )
return false;

return true;
}

Expand Down
2 changes: 2 additions & 0 deletions tests/src/python/qgis_wrapped_server.py
Expand Up @@ -166,6 +166,8 @@ def do_GET(self, post_body=None):
headers = {}
for k, v in self.headers.items():
headers['HTTP_%s' % k.replace(' ', '-').replace('-', '_').replace(' ', '-').upper()] = v
if not self.path.startswith('http'):
self.path = "%s://%s:%s%s" % ('https' if https else 'http', QGIS_SERVER_HOST, QGIS_SERVER_PORT, self.path)
request = QgsBufferServerRequest(self.path, (QgsServerRequest.PostMethod if post_body is not None else QgsServerRequest.GetMethod), headers, post_body)
response = QgsBufferServerResponse()
qgs_server.handleRequest(request, response)
Expand Down

0 comments on commit 479358e

Please sign in to comment.