summaryrefslogtreecommitdiffstats
path: root/src/kernel/qimage.cpp
diff options
context:
space:
mode:
authorSlávek Banko <[email protected]>2020-09-28 15:21:41 +0200
committerSlávek Banko <[email protected]>2020-10-16 15:11:17 +0200
commit7441a646a8b452036daa42d85c98a2105412fd92 (patch)
tree7b755b7d4efdc4963460fd7b4a661f5f8bb749a4 /src/kernel/qimage.cpp
parent66e96fca347628062ade0dd216696e2715168b7a (diff)
downloadtqt3-7441a646a8b452036daa42d85c98a2105412fd92.tar.gz
tqt3-7441a646a8b452036daa42d85c98a2105412fd92.zip
Fix buffer overflow in XBM parser.
Avoid parsing over the buffer limit, or interpreting non-hex as hex. This still leaves parsing of lines longer than 300 chars unreliable. Based on Qt5 patch for CVE-2020-17507. Signed-off-by: Slávek Banko <[email protected]>
Diffstat (limited to 'src/kernel/qimage.cpp')
-rw-r--r--src/kernel/qimage.cpp39
1 files changed, 32 insertions, 7 deletions
diff --git a/src/kernel/qimage.cpp b/src/kernel/qimage.cpp
index 1a31d3acc..1c1d84b2c 100644
--- a/src/kernel/qimage.cpp
+++ b/src/kernel/qimage.cpp
@@ -5512,18 +5512,32 @@ static inline int hex2byte( char *p )
static void read_xbm_image( TQImageIO *iio )
{
const int buflen = 300;
+ const int maxlen = 4096;
char buf[buflen];
TQRegExp r1, r2;
TQIODevice *d = iio->ioDevice();
int w=-1, h=-1;
TQImage image;
+ TQ_INT64 readBytes = 0;
+ TQ_INT64 totalReadBytes = 0;
r1 = TQString::fromLatin1("^#define[ \t]+[a-zA-Z0-9._]+[ \t]+");
r2 = TQString::fromLatin1("[0-9]+");
- d->readLine( buf, buflen ); // "#define .._width <num>"
- while (!d->atEnd() && buf[0] != '#') //skip leading comment, if any
- d->readLine( buf, buflen );
+ buf[0] = '\0';
+ while (buf[0] != '#') { //skip leading comment, if any
+ readBytes = d->readLine(buf, buflen);
+
+ // if readBytes >= buflen, it's very probably not a C file
+ if ((readBytes <= 0) || (readBytes >= (buflen-1)))
+ return;
+
+ // limit xbm headers to the first 4k in the file to prevent
+ // excessive reads on non-xbm files
+ totalReadBytes += readBytes;
+ if (totalReadBytes >= maxlen)
+ return;
+ }
TQString sbuf;
sbuf = TQString::fromLatin1(buf);
@@ -5532,7 +5546,10 @@ static void read_xbm_image( TQImageIO *iio )
r2.search(sbuf, r1.matchedLength()) == r1.matchedLength() )
w = atoi( &buf[r1.matchedLength()] );
- d->readLine( buf, buflen ); // "#define .._height <num>"
+ readBytes = d->readLine(buf, buflen ); // "#define .._height <num>"
+ if (readBytes <= 0) {
+ return;
+ }
sbuf = TQString::fromLatin1(buf);
if ( r1.search(sbuf) == 0 &&
@@ -5543,8 +5560,11 @@ static void read_xbm_image( TQImageIO *iio )
return; // format error
for ( ;; ) { // scan for data
- if ( d->readLine(buf, buflen) <= 0 ) // end of file
+ readBytes = d->readLine(buf, buflen);
+ if (readBytes <= 0) { // end of file
return;
+ }
+ buf[readBytes] = '\0';
if ( strstr(buf,"0x") != 0 ) // does line contain data?
break;
}
@@ -5562,7 +5582,10 @@ static void read_xbm_image( TQImageIO *iio )
w = (w+7)/8; // byte width
while ( y < h ) { // for all encoded bytes...
- if ( p ) { // p = "0x.."
+ if (p && (p < (buf + readBytes - 3))) { // p = "0x.."
+ if (!isxdigit(p[2]) || !isxdigit(p[3])) {
+ return;
+ }
*b++ = hex2byte(p+2);
p += 2;
if ( ++x == w && ++y < h ) {
@@ -5571,8 +5594,10 @@ static void read_xbm_image( TQImageIO *iio )
}
p = strstr( p, "0x" );
} else { // read another line
- if ( d->readLine(buf,buflen) <= 0 ) // EOF ==> truncated image
+ readBytes = d->readLine(buf, buflen);
+ if (readBytes <= 0) // EOF ==> truncated image
break;
+ buf[readBytes] = '\0';
p = strstr( buf, "0x" );
}
}