mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2026-08-26 08:26:59 -04:00
rgb: reject RLE start offsets that underflow the raster data
The start table is stored as file offsets. We subtract the header+table size to get an index into the remaining data. If the file offset is smaller than that, the subtract wraps and the later start+length check can wrap too. Drop the file instead of walking off the buffer.
This commit is contained in:
@@ -314,6 +314,8 @@ bool SGIImagePrivate::readImage(QImage &img)
|
|||||||
_numrows = _ysize * _zsize;
|
_numrows = _ysize * _zsize;
|
||||||
|
|
||||||
if (_rle) {
|
if (_rle) {
|
||||||
|
// start table holds file offsets; raster data follows header + both tables
|
||||||
|
const quint32 dataOff = 512 + _numrows * 2 * sizeof(quint32);
|
||||||
uint l;
|
uint l;
|
||||||
_starttab = new (std::nothrow) quint32[_numrows];
|
_starttab = new (std::nothrow) quint32[_numrows];
|
||||||
if (_starttab == nullptr) {
|
if (_starttab == nullptr) {
|
||||||
@@ -321,7 +323,10 @@ bool SGIImagePrivate::readImage(QImage &img)
|
|||||||
}
|
}
|
||||||
for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
|
for (l = 0; !_stream.atEnd() && l < _numrows; l++) {
|
||||||
_stream >> _starttab[l];
|
_stream >> _starttab[l];
|
||||||
_starttab[l] -= 512 + _numrows * 2 * sizeof(quint32);
|
if (_starttab[l] < dataOff) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_starttab[l] -= dataOff;
|
||||||
if (_stream.status() != QDataStream::Ok) {
|
if (_stream.status() != QDataStream::Ok) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -353,9 +358,10 @@ bool SGIImagePrivate::readImage(QImage &img)
|
|||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
if (_rle) {
|
if (_rle) {
|
||||||
|
const uint dataSize = uint(_data.size());
|
||||||
for (uint o = 0; o < _numrows; o++) {
|
for (uint o = 0; o < _numrows; o++) {
|
||||||
// don't change to greater-or-equal!
|
// don't add start+length: uint32 wrap would pass a corrupt file
|
||||||
if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
|
if (_starttab[o] > dataSize || _lengthtab[o] > dataSize - _starttab[o]) {
|
||||||
// qCDebug(LOG_RGBPLUGIN) << "image corrupt (sanity check failed)";
|
// qCDebug(LOG_RGBPLUGIN) << "image corrupt (sanity check failed)";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user