Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8314112

NegativeArraySizeException during print when scaling causes w and h to be 0

XMLWordPrintable

    • 2d
    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Java version: 20.0.2, vendor: Oracle Corporation, runtime: <PATH>
      Default locale: en_US, platform encoding: UTF-8
      OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
      ---
      Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
      PDFBox 2.0.27

      A DESCRIPTION OF THE PROBLEM :
      The `sun.awt.windows.WPathGraphics` class in Java contains a code segment within the `drawImageToPlatform` function that can lead to a `NegativeArraySizeException` under specific conditions. This issue arises when the scaling values in `AffineTransform` are set in a way that causes `w` and `h` (width and height) to have a value of 0.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Extract the attached java maven project on a windows system and execute "mvn test".
      2. Choose the "Microsoft Print to PDF" Printer and hit "Print".
      3. Choose a file destination for the final PDF.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The `drawImageToPlatform` function should handle the scaling gracefully without causing any exceptions and continue to execute as intended.
      ACTUAL -
      Due to the presence of 0 in `w` or `h`, the subsequent calculation of `minDpi` causes a division by zero, leading to a `NegativeArraySizeException`. This exception disrupts the normal execution flow and may lead to unexpected behavior or application crashes.

      ---------- BEGIN SOURCE ----------
      package com.example;

      import static org.junit.Assert.assertNotNull;
      import static org.junit.Assert.fail;

      import java.awt.Color;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.geom.AffineTransform;
      import java.awt.print.PageFormat;
      import java.awt.print.Printable;
      import java.awt.print.PrinterJob;

      import javax.print.PrintService;
      import javax.print.PrintServiceLookup;
      import javax.print.attribute.HashPrintRequestAttributeSet;
      import javax.print.attribute.PrintRequestAttributeSet;
      import javax.print.attribute.standard.Copies;

      import org.apache.pdfbox.pdmodel.PDDocument;
      import org.apache.pdfbox.pdmodel.PDPage;
      import org.apache.pdfbox.rendering.PDFRenderer;
      import org.apache.pdfbox.rendering.RenderDestination;
      import org.junit.Test;

      public class PDFPrintTest {

          /**
           * A NegativeArraySizeException occurs when printing the first page of the PDF document.
           *
           * Stacktrace:
           * java.lang.NegativeArraySizeException: -1808096928
           * at java.desktop/java.awt.image.DataBufferByte.<init>(DataBufferByte.java:76)
           * at java.desktop/java.awt.image.Raster.createInterleavedRaster(Raster.java:266)
           * at java.desktop/java.awt.image.BufferedImage.<init>(BufferedImage.java:376)
           * at java.desktop/sun.awt.windows.WPathGraphics.redrawRegion(WPathGraphics.java:1401)
           * at java.desktop/sun.print.RasterPrinterJob.printPage(RasterPrinterJob.java:2320)
           * at java.desktop/sun.print.RasterPrinterJob.print(RasterPrinterJob.java:1654)
           * at com.example.PDFPrintTest.test(PDFPrintTest.java:67)
           *
           * Stacktrace in newer Java Version. For example jdk-20.0.2:
           * java.lang.IllegalArgumentException: Dimensions (width=3358932 height=3358888) are too large
           * at java.desktop/java.awt.image.Raster.createInterleavedRaster(Raster.java:285)
           * at java.desktop/java.awt.image.BufferedImage.<init>(BufferedImage.java:376)
           * at java.desktop/sun.awt.windows.WPathGraphics.redrawRegion(WPathGraphics.java:1404)
           * at java.desktop/sun.print.RasterPrinterJob.printPage(RasterPrinterJob.java:2323)
           * at java.desktop/sun.print.RasterPrinterJob.print(RasterPrinterJob.java:1657)
           * at com.example.PDFPrintTest.test(PDFPrintTest.java:68)
           */
          @Test
          public void test() throws Exception {

              // Load the PDF document
              try (PDDocument document = PDDocument.load(PDFPrintTest.class.getResourceAsStream("/1x1PixelPrintProblem.pdf"))) {

                  // Get the default printer
                  PrintService defaultPrinter = PrintServiceLookup.lookupDefaultPrintService();
                  assertNotNull("Printer available", defaultPrinter);

                  PrinterJob printerJob = PrinterJob.getPrinterJob();
                  printerJob.setPrintService(defaultPrinter);

                  // Set print attributes
                  PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
                  attributes.add(new Copies(1)); // Number of copies to print

                  // Set the Printable object to handle custom printing
                  PDFRenderer renderer = new PDFRenderer(document);
                  Printable printable = createPrintableWithScale(document.getPage(0), 0.15f, renderer);

                  // Set the Printable object and attributes to the PrinterJob
                  printerJob.setPrintable(printable);
                  if (printerJob.printDialog(attributes)) {
                      printerJob.print(attributes);
                  }

              }
          }

          // Create a Printable object with scaling
          private static Printable createPrintableWithScale(PDPage page, float scale, PDFRenderer renderer) {
              return (Graphics graphics, PageFormat pageFormat, int pageIndex) -> {
                  if (pageIndex > 0) {
                      return Printable.NO_SUCH_PAGE;
                  }

                  Graphics2D graphics2D = (Graphics2D) graphics;
                  graphics2D.setBackground(Color.WHITE);
                  graphics2D.transform(AffineTransform.getScaleInstance(scale, scale));

                  // Draw the PDF page to the given graphics instance
                  try {
                      renderer.renderPageToGraphics(pageIndex, graphics2D, 1, 1, RenderDestination.PRINT);
                  } catch (Exception e) {
                      fail("Render failed: " + e.getMessage());
                  }

                  return Printable.PAGE_EXISTS;
              };
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            honkar Harshitha Onkar
            webbuggrp Webbug Group
            Votes:
            1 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated: