From e26070634695c845d28199e273fc3b10800bd3cd Mon Sep 17 00:00:00 2001 From: Sharad Boni Date: Wed, 15 Apr 2026 15:50:46 -0700 Subject: [PATCH 1/2] Fix integer overflow in tensor dimensions and PPM parser - util/basics.h: Add overflow check in Extents2D::Area() before computing rows*cols. Malicious model files with large dimension values could cause a silent size_t overflow, leading to undersized allocations and subsequent heap buffer overflows. - paligemma/image.cc: Add overflow check for width*height*3 in ReadPPM(). A crafted PPM file with large dimensions could overflow the data_size computation, resulting in an undersized buffer and out-of-bounds writes. - paligemma/image.cc: Add overflow detection in ParseUnsigned() to reject values that would overflow size_t during decimal parsing. --- paligemma/image.cc | 15 +++++++++++++-- util/basics.h | 7 ++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/paligemma/image.cc b/paligemma/image.cc index 821f9bf0..99071c72 100644 --- a/paligemma/image.cc +++ b/paligemma/image.cc @@ -83,8 +83,11 @@ const char* ParseUnsigned(const char* pos, const char* end, size_t& num) { } num = 0; for (; pos < end && std::isdigit(*pos); ++pos) { - num *= 10; - num += *pos - '0'; + const size_t digit = *pos - '0'; + if (num > (SIZE_MAX - digit) / 10) { + return nullptr; // overflow + } + num = num * 10 + digit; } return pos; } @@ -136,6 +139,14 @@ bool Image::ReadPPM(const hwy::Span& buf) { return false; } ++pos; + if (width == 0 || height == 0) { + std::cerr << "Invalid zero dimension\n"; + return false; + } + if (width > SIZE_MAX / 3 || width * 3 > SIZE_MAX / height) { + std::cerr << "Image dimensions overflow\n"; + return false; + } const size_t data_size = width * height * 3; if (buf.cend() - pos < static_cast(data_size)) { std::cerr << "Insufficient data remaining\n"; diff --git a/util/basics.h b/util/basics.h index bfab3f89..28e8ee2b 100644 --- a/util/basics.h +++ b/util/basics.h @@ -97,7 +97,12 @@ struct Extents2D { constexpr Extents2D() : rows(0), cols(0) {} constexpr Extents2D(size_t rows, size_t cols) : rows(rows), cols(cols) {} - size_t Area() const { return rows * cols; } + size_t Area() const { + if (rows != 0 && cols > SIZE_MAX / rows) { + HWY_ABORT("Tensor dimension overflow: rows=%zu cols=%zu", rows, cols); + } + return rows * cols; + } size_t rows; size_t cols; From c4d14dbc22f42180ee28b33ed0bbbec960b4c5c3 Mon Sep 17 00:00:00 2001 From: Sharad Boni Date: Thu, 16 Apr 2026 09:02:04 -0700 Subject: [PATCH 2/2] Use HWY_ABORT instead of std::cerr for overflow checks in ReadPPM --- paligemma/image.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paligemma/image.cc b/paligemma/image.cc index 99071c72..b2c54195 100644 --- a/paligemma/image.cc +++ b/paligemma/image.cc @@ -140,11 +140,11 @@ bool Image::ReadPPM(const hwy::Span& buf) { } ++pos; if (width == 0 || height == 0) { - std::cerr << "Invalid zero dimension\n"; + HWY_ABORT("Invalid zero dimension\n"); return false; } if (width > SIZE_MAX / 3 || width * 3 > SIZE_MAX / height) { - std::cerr << "Image dimensions overflow\n"; + HWY_ABORT("Image dimensions overflow\n"); return false; } const size_t data_size = width * height * 3;