Reject truncated and corrupt ascii pnm images

In contrast to the binary decoder code, the ascii decoder would not
abort and fail on premature end of file.

Pick-to: 6.2 6.2.2 5.15 5.12 5.12.12
Change-Id: If27bce0afa8d1de6c4dbeb2bc0e623c1dcc2f1e0
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Eirik Aavitsland 2021-11-16 07:41:20 +01:00 committed by Volker Hilsheimer
parent 99bb78f6c2
commit 997c052db9
1 changed files with 27 additions and 22 deletions

View File

@ -68,7 +68,7 @@ static void discard_pbm_line(QIODevice *d)
} while (res > 0 && buf[res-1] != '\n');
}
static int read_pbm_int(QIODevice *d)
static int read_pbm_int(QIODevice *d, bool *ok)
{
char c;
int val = -1;
@ -102,6 +102,8 @@ static int read_pbm_int(QIODevice *d)
else
break;
}
if (val < 0)
*ok = false;
return hasOverflow ? -1 : val;
}
@ -118,16 +120,17 @@ static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int&
if (type < '1' || type > '6')
return false;
w = read_pbm_int(device); // get image width
h = read_pbm_int(device); // get image height
bool ok = true;
w = read_pbm_int(device, &ok); // get image width
h = read_pbm_int(device, &ok); // get image height
if (type == '1' || type == '4')
mcc = 1; // ignore max color component
else
mcc = read_pbm_int(device); // get max color component
mcc = read_pbm_int(device, &ok); // get max color component
if (w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
return false; // weird P.M image
if (!ok || w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
return false; // weird P.M image
return true;
}
@ -235,18 +238,18 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
} else { // read ascii data
uchar *p;
qsizetype n;
char buf;
for (y = 0; (y < h) && (device->peek(&buf, 1) == 1); y++) {
bool ok = true;
for (y = 0; y < h && ok; y++) {
p = outImage->scanLine(y);
n = pbm_bpl;
if (nbits == 1) {
int b;
int bitsLeft = w;
while (n--) {
while (n-- && ok) {
b = 0;
for (int i=0; i<8; i++) {
if (i < bitsLeft)
b = (b << 1) | (read_pbm_int(device) & 1);
b = (b << 1) | (read_pbm_int(device, &ok) & 1);
else
b = (b << 1) | (0 & 1); // pad it our self if we need to
}
@ -255,36 +258,38 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
}
} else if (nbits == 8) {
if (mcc == 255) {
while (n--) {
*p++ = read_pbm_int(device);
while (n-- && ok) {
*p++ = read_pbm_int(device, &ok);
}
} else {
while (n--) {
*p++ = (read_pbm_int(device) & 0xffff) * 255 / mcc;
while (n-- && ok) {
*p++ = (read_pbm_int(device, &ok) & 0xffff) * 255 / mcc;
}
}
} else { // 32 bits
n /= 4;
int r, g, b;
if (mcc == 255) {
while (n--) {
r = read_pbm_int(device);
g = read_pbm_int(device);
b = read_pbm_int(device);
while (n-- && ok) {
r = read_pbm_int(device, &ok);
g = read_pbm_int(device, &ok);
b = read_pbm_int(device, &ok);
*((QRgb*)p) = qRgb(r, g, b);
p += 4;
}
} else {
while (n--) {
r = read_pbm_int(device);
g = read_pbm_int(device);
b = read_pbm_int(device);
while (n-- && ok) {
r = read_pbm_int(device, &ok);
g = read_pbm_int(device, &ok);
b = read_pbm_int(device, &ok);
*((QRgb*)p) = scale_pbm_color(mcc, r, g, b);
p += 4;
}
}
}
}
if (!ok)
return false;
}
if (format == QImage::Format_Mono) {