mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
[Server] QgsWmsRenderContext::isValidWidthHeight(): rewrite sanity checks in a foolproof way
The check for ``width * depth + 31`` not overflowing INT_MAX was done after computing it, which would be undefined behavior if that happened. Nowadays compilers can use "impossible situations" in smart ways, and could very well discard the check if it is done afterwards. Be on the safe sife and check before, as done in https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/image/qimage_p.h#n89
This commit is contained in:
parent
98017509f7
commit
5d97f57947
@ -650,6 +650,9 @@ bool QgsWmsRenderContext::isValidWidthHeight() const
|
|||||||
|
|
||||||
bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
|
bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
|
||||||
{
|
{
|
||||||
|
if ( width <= 0 || height <= 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
//test if maxWidth / maxHeight are set in the project or as an env variable
|
//test if maxWidth / maxHeight are set in the project or as an env variable
|
||||||
//and WIDTH / HEIGHT parameter is in the range allowed range
|
//and WIDTH / HEIGHT parameter is in the range allowed range
|
||||||
//WIDTH
|
//WIDTH
|
||||||
@ -692,14 +695,15 @@ bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check from internal QImage checks (see qimage.cpp)
|
// Sanity check from internal QImage checks
|
||||||
|
// (see QImageData::calculateImageParameters() in qimage_p.h)
|
||||||
// this is to report a meaningful error message in case of
|
// this is to report a meaningful error message in case of
|
||||||
// image creation failure and to differentiate it from out
|
// image creation failure and to differentiate it from out
|
||||||
// of memory conditions.
|
// of memory conditions.
|
||||||
|
|
||||||
// depth for now it cannot be anything other than 32, but I don't like
|
// 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.
|
// to hardcode it: I hope we will support other depths in the future.
|
||||||
uint depth = 32;
|
int depth = 32;
|
||||||
switch ( mParameters.format() )
|
switch ( mParameters.format() )
|
||||||
{
|
{
|
||||||
case QgsWmsParameters::Format::JPG:
|
case QgsWmsParameters::Format::JPG:
|
||||||
@ -708,12 +712,12 @@ bool QgsWmsRenderContext::isValidWidthHeight( int width, int height ) const
|
|||||||
depth = 32;
|
depth = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( width > ( std::numeric_limits<int>::max() - 31 ) / depth )
|
||||||
|
return false;
|
||||||
|
|
||||||
const int bytes_per_line = ( ( width * depth + 31 ) >> 5 ) << 2; // bytes per scanline (must be multiple of 4)
|
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 < static_cast<uint>( width )
|
if ( std::numeric_limits<int>::max() / bytes_per_line < height
|
||||||
|| bytes_per_line <= 0
|
|
||||||
|| height <= 0
|
|
||||||
|| std::numeric_limits<int>::max() / static_cast<uint>( bytes_per_line ) < static_cast<uint>( height )
|
|
||||||
|| std::numeric_limits<int>::max() / sizeof( uchar * ) < static_cast<uint>( height ) )
|
|| std::numeric_limits<int>::max() / sizeof( uchar * ) < static_cast<uint>( height ) )
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -336,6 +336,25 @@ class TestQgsServerWMSGetMap(QgsServerTestBase):
|
|||||||
err = b"HEIGHT (\'FOO\') cannot be converted into int" in r
|
err = b"HEIGHT (\'FOO\') cannot be converted into int" in r
|
||||||
self.assertTrue(err)
|
self.assertTrue(err)
|
||||||
|
|
||||||
|
# height should be > 0
|
||||||
|
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
||||||
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
|
"SERVICE": "WMS",
|
||||||
|
"VERSION": "1.1.1",
|
||||||
|
"REQUEST": "GetMap",
|
||||||
|
"LAYERS": "Country",
|
||||||
|
"STYLES": "",
|
||||||
|
"FORMAT": "image/png",
|
||||||
|
"BBOX": "-16817707,-4710778,5696513,14587125",
|
||||||
|
"HEIGHT": "-1",
|
||||||
|
"WIDTH": "1",
|
||||||
|
"CRS": "EPSG:3857"
|
||||||
|
}.items())])
|
||||||
|
|
||||||
|
r, h = self._result(self._execute_request(qs))
|
||||||
|
err = b"The requested map size is too large" in r
|
||||||
|
self.assertTrue(err)
|
||||||
|
|
||||||
# width should be an int
|
# width should be an int
|
||||||
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
||||||
"MAP": urllib.parse.quote(self.projectPath),
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
@ -355,6 +374,25 @@ class TestQgsServerWMSGetMap(QgsServerTestBase):
|
|||||||
err = b"WIDTH (\'FOO\') cannot be converted into int" in r
|
err = b"WIDTH (\'FOO\') cannot be converted into int" in r
|
||||||
self.assertTrue(err)
|
self.assertTrue(err)
|
||||||
|
|
||||||
|
# width should be > 0
|
||||||
|
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
||||||
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
|
"SERVICE": "WMS",
|
||||||
|
"VERSION": "1.1.1",
|
||||||
|
"REQUEST": "GetMap",
|
||||||
|
"LAYERS": "Country",
|
||||||
|
"STYLES": "",
|
||||||
|
"FORMAT": "image/png",
|
||||||
|
"BBOX": "-16817707,-4710778,5696513,14587125",
|
||||||
|
"HEIGHT": "1",
|
||||||
|
"WIDTH": "-1",
|
||||||
|
"CRS": "EPSG:3857"
|
||||||
|
}.items())])
|
||||||
|
|
||||||
|
r, h = self._result(self._execute_request(qs))
|
||||||
|
err = b"The requested map size is too large" in r
|
||||||
|
self.assertTrue(err)
|
||||||
|
|
||||||
# bbox should be formatted like "double,double,double,double"
|
# bbox should be formatted like "double,double,double,double"
|
||||||
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
qs = "?" + "&".join(["%s=%s" % i for i in list({
|
||||||
"MAP": urllib.parse.quote(self.projectPath),
|
"MAP": urllib.parse.quote(self.projectPath),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user