From 01272c0948be9f1c6b8a3eff328b931f47d38649 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 16 Nov 2021 07:41:20 +0100 Subject: 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. Change-Id: If27bce0afa8d1de6c4dbeb2bc0e623c1dcc2f1e0 Reviewed-by: Volker Hilsheimer (cherry picked from commit 997c052db9e2bef47cf8217c1537a99c2f086858) Reviewed-by: Eirik Aavitsland --- src/gui/image/qppmhandler.cpp | 47 ++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index 53e3fa293d..36a449c841 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -63,7 +63,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; @@ -91,6 +91,8 @@ static int read_pbm_int(QIODevice *d) else break; } + if (val < 0) + *ok = false; return val; } @@ -107,16 +109,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; } @@ -227,18 +230,18 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q } else { // read ascii data uchar *p; int 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 } @@ -247,36 +250,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) * 255 / mcc; + *p++ = read_pbm_int(device, &ok) * 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) { -- cgit v1.2.3