Skip to content

Integer overflow in ReadOther size check in image_prepare.cpp #301

@AlexMelanFromRingo

Description

@AlexMelanFromRingo

ReadOther in ui/image/image_prepare.cpp (function ReadOther, currently line 458):

	const auto size = reader.size();
	if (size.width() * size.height() > kReadMaxArea) {
		return {};
	}

QSize::width() and QSize::height() return int, so size.width() * size.height() is evaluated in int. kReadMaxArea is 12032 * 9024. QImageReader::size() returns the dimensions declared in the file header before decoding, so a crafted file can declare very large dimensions.

For a header that declares 65536 x 65536 the int product is 0, the check passes, and reader.read(&result.image) proceeds to allocate a QImage for the declared size (a 65536x65536 ARGB image is 16 GiB). Other dimensions whose product wraps below kReadMaxArea (for example 65535 x 65535, or 32768 x 65536 which wraps negative) pass the same way. JPEG and WebP are affected too, since QImageReader::size() reports header dimensions for them as well.

Minimal repro. This 68-byte PNG declares 65536 x 65536 in IHDR:

import struct, zlib
def chunk(t, d):
    return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d))
open("overflow.png", "wb").write(
    b"\x89PNG\r\n\x1a\n"
    + chunk(b"IHDR", struct.pack(">II", 65536, 65536) + bytes([8, 2, 0, 0, 0]))
    + chunk(b"IDAT", zlib.compress(b"\x00" * 16))
    + chunk(b"IEND", b""))

QImageReader on this file returns size() == 65536x65536; int(65536 * 65536) is 0; the guard passes.

Suggested fix, reject non-positive dimensions and widen the multiplication to qint64:

 	const auto size = reader.size();
-	if (size.width() * size.height() > kReadMaxArea) {
+	if (size.width() <= 0 || size.height() <= 0) {
+		return {};
+	}
+	if (qint64(size.width()) * size.height() > kReadMaxArea) {
 		return {};
 	}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions