[frameworks/kimageformats] src/imageformats: rgb: reject RLE start offsets that underflow the raster data

Aljo Joby <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 09452b0964d7ccf1b370a0b07973acf810959139 by Aljo Joby.
Committed on 14/08/2026 at 15:33.
Pushed by aacid into branch 'master'.

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.

M  +9    -3    src/imageformats/rgb.cpp

https://invent.kde.org/frameworks/kimageformats/-/commit/09452b0964d7ccf1b370a0b07973acf810959139

diff --git a/src/imageformats/rgb.cpp b/src/imageformats/rgb.cpp
index 1052fac4..17bda896 100644
--- a/src/imageformats/rgb.cpp
+++ b/src/imageformats/rgb.cpp
@@ -314,6 +314,8 @@ bool SGIImagePrivate::readImage(QImage &img)
     _numrows = _ysize * _zsize;
 
     if (_rle) {
+        // start table holds file offsets; raster data follows header + both tables
+        const quint32 dataOff = 512 + _numrows * 2 * sizeof(quint32);
         uint l;
         _starttab = new (std::nothrow) quint32[_numrows];
         if (_starttab == nullptr) {
@@ -321,7 +323,10 @@ bool SGIImagePrivate::readImage(QImage &img)
         }
         for (l = 0; !_stream.atEnd() && l < _numrows; 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) {
                 return false;
             }
@@ -353,9 +358,10 @@ bool SGIImagePrivate::readImage(QImage &img)
 
     // sanity check
     if (_rle) {
+        const uint dataSize = uint(_data.size());
         for (uint o = 0; o < _numrows; o++) {
-            // don't change to greater-or-equal!
-            if (_starttab[o] + _lengthtab[o] > (uint)_data.size()) {
+            // don't add start+length: uint32 wrap would pass a corrupt file
+            if (_starttab[o] > dataSize || _lengthtab[o] > dataSize - _starttab[o]) {
                 //                 qCDebug(LOG_RGBPLUGIN) << "image corrupt (sanity check failed)";
                 return false;
             }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.