From 55b6bb4d5afe249677c3f276094a0a0fa1f103d7 Mon Sep 17 00:00:00 2001 From: alhudz Date: Fri, 5 Jun 2026 20:32:11 +0530 Subject: [PATCH 1/3] fix int overflow in pcx image buffer sizing --- .../apache/commons/imaging/formats/pcx/PcxImageParser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/imaging/formats/pcx/PcxImageParser.java b/src/main/java/org/apache/commons/imaging/formats/pcx/PcxImageParser.java index a158ac8d4d..625ecda992 100644 --- a/src/main/java/org/apache/commons/imaging/formats/pcx/PcxImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/pcx/PcxImageParser.java @@ -311,7 +311,7 @@ private BufferedImage readImage(final PcxHeader pcxHeader, final InputStream is, if ((pcxHeader.bitsPerPixel == 1 || pcxHeader.bitsPerPixel == 2 || pcxHeader.bitsPerPixel == 4 || pcxHeader.bitsPerPixel == 8) && pcxHeader.nPlanes == 1) { final int bytesPerImageRow = (xSize * pcxHeader.bitsPerPixel + 7) / 8; - final byte[] image = Allocator.byteArray(ySize * bytesPerImageRow); + final byte[] image = Allocator.byteArray((long) ySize * bytesPerImageRow); for (int y = 0; y < ySize; y++) { rleReader.read(is, scanline); System.arraycopy(scanline, 0, image, y * bytesPerImageRow, bytesPerImageRow); @@ -370,7 +370,7 @@ private BufferedImage readImage(final PcxHeader pcxHeader, final InputStream is, } if (pcxHeader.bitsPerPixel == 8 && pcxHeader.nPlanes == 3) { final byte[][] image = new byte[3][]; - final int xySize = xSize * ySize; + final long xySize = (long) xSize * ySize; image[0] = Allocator.byteArray(xySize); image[1] = Allocator.byteArray(xySize); image[2] = Allocator.byteArray(xySize); @@ -390,7 +390,7 @@ private BufferedImage readImage(final PcxHeader pcxHeader, final InputStream is, throw new ImagingException("Invalid/unsupported image with bitsPerPixel " + pcxHeader.bitsPerPixel + " and planes " + pcxHeader.nPlanes); } final int rowLength = 3 * xSize; - final byte[] image = Allocator.byteArray(rowLength * ySize); + final byte[] image = Allocator.byteArray((long) rowLength * ySize); for (int y = 0; y < ySize; y++) { rleReader.read(is, scanline); if (pcxHeader.bitsPerPixel == 24) { From 5b64d8084ad6881d062a5f9c2f6766ddbb8a8399 Mon Sep 17 00:00:00 2001 From: alhudz Date: Mon, 22 Jun 2026 14:43:09 +0530 Subject: [PATCH 2/3] add test for pcx image buffer size overflow --- .../formats/pcx/PcxImageParserTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java diff --git a/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java b/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java new file mode 100644 index 0000000000..8265e52d81 --- /dev/null +++ b/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.imaging.formats.pcx; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.apache.commons.imaging.common.AllocationRequestException; +import org.junit.jupiter.api.Test; + +class PcxImageParserTest { + + /** + * A 24-bit PCX header whose width and height are both 65536 makes {@code rowLength * ySize} overflow {@code int} and wrap to a tiny value, which used to + * slip past the {@link AllocationRequestException} guard and allocate an undersized buffer. The size is now computed in {@code long}, so the real request is + * rejected. + */ + @Test + void testBufferSizeOverflow() { + final byte[] bytes = new byte[128]; + bytes[0] = 10; // manufacturer + bytes[1] = 5; // version + bytes[2] = 0; // encoding (uncompressed) + bytes[3] = 24; // bitsPerPixel + // xMin = 0, yMin = 0 + // xMax = 65535 (little-endian), so xSize = 65536 + bytes[8] = (byte) 0xFF; + bytes[9] = (byte) 0xFF; + // yMax = 65535 (little-endian), so ySize = 65536 + bytes[10] = (byte) 0xFF; + bytes[11] = (byte) 0xFF; + bytes[65] = 1; // nPlanes + bytes[66] = 8; // bytesPerLine + assertThrows(AllocationRequestException.class, () -> new PcxImageParser().getBufferedImage(bytes, null)); + } +} From ba59921fde3aeaf13ba99e202c9bd5094af864d0 Mon Sep 17 00:00:00 2001 From: Alhuda Khan Date: Tue, 23 Jun 2026 13:08:14 +0530 Subject: [PATCH 3/3] wrap test javadoc to satisfy checkstyle line length --- .../commons/imaging/formats/pcx/PcxImageParserTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java b/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java index 8265e52d81..683b52b86f 100644 --- a/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java +++ b/src/test/java/org/apache/commons/imaging/formats/pcx/PcxImageParserTest.java @@ -26,8 +26,8 @@ class PcxImageParserTest { /** * A 24-bit PCX header whose width and height are both 65536 makes {@code rowLength * ySize} overflow {@code int} and wrap to a tiny value, which used to - * slip past the {@link AllocationRequestException} guard and allocate an undersized buffer. The size is now computed in {@code long}, so the real request is - * rejected. + * slip past the {@link AllocationRequestException} guard and allocate an undersized buffer. The size is now computed in {@code long}, so the real + * request is rejected. */ @Test void testBufferSizeOverflow() {