From 193cfde5b5c0f4950a423fc56c0070c597335ef0 Mon Sep 17 00:00:00 2001 From: subbudvk <115633743+subbudvk@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:28:34 +0530 Subject: [PATCH 1/4] Validate dimensions to avoid OOM Exception --- .../apache/pdfbox/filter/CCITTFaxFilter.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java index c86937421c9..5cf11e580da 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java @@ -59,8 +59,31 @@ public DecodeResult decode(InputStream encoded, OutputStream decoded, // decompress data int k = decodeParms.getInt(COSName.K, 0); boolean encodedByteAlign = decodeParms.getBoolean(COSName.ENCODED_BYTE_ALIGN, false); - int arraySize = (cols + 7) / 8 * rows; - // TODO possible options?? + if (cols <= 0 || rows <= 0) + { + throw new IOException("Invalid CCITT image dimensions: cols=" + cols + ", rows=" + rows); + } + long arraySizeLong = ((long) cols + 7) / 8 * rows; + long maxBytes = 256 * 1024 * 1024L; + String sysProp = System.getProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES); + if (sysProp != null) + { + try + { + maxBytes = Long.parseLong(sysProp); + } + catch (NumberFormatException e) + { + // ignore invalid value, keep default + } + } + if (arraySizeLong > maxBytes) + { + throw new IOException("CCITT decode buffer too large (" + arraySizeLong + + " bytes) for cols=" + cols + ", rows=" + rows + + "; increase " + Filter.SYSPROP_CCITTFAX_MAXBYTES + " to override"); + } + int arraySize = (int) arraySizeLong; byte[] decompressed = new byte[arraySize]; CCITTFaxDecoderStream s; int type; From 75db7a095989472fc511670aeb60f2cef011613e Mon Sep 17 00:00:00 2001 From: subbudvk <115633743+subbudvk@users.noreply.github.com> Date: Wed, 8 Apr 2026 21:29:38 +0530 Subject: [PATCH 2/4] Fix : Validate dimensions in user pdf. --- .../src/main/java/org/apache/pdfbox/filter/Filter.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java b/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java index eb6d366ae5f..a53cd63e520 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/filter/Filter.java @@ -60,6 +60,16 @@ public abstract class Filter */ public static final String SYSPROP_DEFLATELEVEL = "org.apache.pdfbox.filter.deflatelevel"; + /** + * CCITTFax decode buffer size cap System Property. Sets the maximum number of bytes that + * CCITTFaxFilter is allowed to pre-allocate for a single image decode buffer. PDF-controlled + * /Columns and /Rows values are validated against this limit before allocation to prevent + * denial-of-service via crafted image dimensions. The default is 256 MB. To raise the cap for + * high-resolution legitimate documents, use + * {@code System.setProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES, String.valueOf(512 * 1024 * 1024L));} + */ + public static final String SYSPROP_CCITTFAX_MAXBYTES = "org.apache.pdfbox.filter.ccittmaxbytes"; + /** * Constructor. */ From fddec871e29610350a373027545c6b4de53c8e18 Mon Sep 17 00:00:00 2001 From: subbudvk <115633743+subbudvk@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:10:16 +0530 Subject: [PATCH 3/4] Fix user controlled dimensions to avoid OOM --- .../apache/pdfbox/filter/CCITTFaxFilter.java | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java index 5cf11e580da..fa4efcf862d 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java @@ -64,25 +64,41 @@ public DecodeResult decode(InputStream encoded, OutputStream decoded, throw new IOException("Invalid CCITT image dimensions: cols=" + cols + ", rows=" + rows); } long arraySizeLong = ((long) cols + 7) / 8 * rows; - long maxBytes = 256 * 1024 * 1024L; - String sysProp = System.getProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES); - if (sysProp != null) - { - try - { - maxBytes = Long.parseLong(sysProp); - } - catch (NumberFormatException e) - { - // ignore invalid value, keep default - } - } - if (arraySizeLong > maxBytes) + if (cols <= 0 || rows <= 0) +{ + throw new IOException("Invalid CCITT image dimensions: cols=" + cols + ", rows=" + rows); +} + +long arraySizeLong = ((long) cols + 7) / 8 * rows; + +long maxBytes = 256 * 1024 * 1024L; +String sysProp = System.getProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES); + +if (sysProp != null) +{ + try + { + long parsed = Long.parseLong(sysProp); + if (parsed > 0) { - throw new IOException("CCITT decode buffer too large (" + arraySizeLong - + " bytes) for cols=" + cols + ", rows=" + rows - + "; increase " + Filter.SYSPROP_CCITTFAX_MAXBYTES + " to override"); + maxBytes = parsed; } + // else ignore zero/negative values + } + catch (NumberFormatException e) + { + // ignore invalid value, keep default + } +} + +if (arraySizeLong > maxBytes) +{ + throw new IOException( + "CCITT decode buffer too large (" + arraySizeLong + " bytes) for cols=" + cols + + ", rows=" + rows + "; max allowed=" + maxBytes + + "; increase " + Filter.SYSPROP_CCITTFAX_MAXBYTES + " to override" + ); +} int arraySize = (int) arraySizeLong; byte[] decompressed = new byte[arraySize]; CCITTFaxDecoderStream s; From 909a8b6d7124a734946bb3f831acc042b2d05c54 Mon Sep 17 00:00:00 2001 From: subbudvk <115633743+subbudvk@users.noreply.github.com> Date: Wed, 8 Apr 2026 23:20:23 +0530 Subject: [PATCH 4/4] Update CCITTFaxFilter.java --- .../apache/pdfbox/filter/CCITTFaxFilter.java | 53 +++++++++---------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java index fa4efcf862d..4087f836247 100644 --- a/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java +++ b/pdfbox/src/main/java/org/apache/pdfbox/filter/CCITTFaxFilter.java @@ -63,41 +63,36 @@ public DecodeResult decode(InputStream encoded, OutputStream decoded, { throw new IOException("Invalid CCITT image dimensions: cols=" + cols + ", rows=" + rows); } - long arraySizeLong = ((long) cols + 7) / 8 * rows; - if (cols <= 0 || rows <= 0) -{ - throw new IOException("Invalid CCITT image dimensions: cols=" + cols + ", rows=" + rows); -} -long arraySizeLong = ((long) cols + 7) / 8 * rows; + long arraySizeLong = ((long) cols + 7) / 8 * rows; -long maxBytes = 256 * 1024 * 1024L; -String sysProp = System.getProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES); + long maxBytes = 256 * 1024 * 1024L; + String sysProp = System.getProperty(Filter.SYSPROP_CCITTFAX_MAXBYTES); -if (sysProp != null) -{ - try - { - long parsed = Long.parseLong(sysProp); - if (parsed > 0) + if (sysProp != null) { - maxBytes = parsed; - } + try + { + long parsed = Long.parseLong(sysProp); + if (parsed > 0) + { + maxBytes = parsed; + } // else ignore zero/negative values - } - catch (NumberFormatException e) - { - // ignore invalid value, keep default - } -} + } + catch (NumberFormatException e) + { + // ignore invalid value, keep default + } + } -if (arraySizeLong > maxBytes) -{ - throw new IOException( - "CCITT decode buffer too large (" + arraySizeLong + " bytes) for cols=" + cols + - ", rows=" + rows + "; max allowed=" + maxBytes + - "; increase " + Filter.SYSPROP_CCITTFAX_MAXBYTES + " to override" - ); + if (arraySizeLong > maxBytes) + { + throw new IOException( + "CCITT decode buffer too large (" + arraySizeLong + " bytes) for cols=" + cols + + ", rows=" + rows + "; max allowed=" + maxBytes + + "; increase " + Filter.SYSPROP_CCITTFAX_MAXBYTES + " to override" + ); } int arraySize = (int) arraySizeLong; byte[] decompressed = new byte[arraySize];