Nicholas Moser created XGC-136:
----------------------------------

             Summary: 2.8 Out of memory on certain malformed PNGs
                 Key: XGC-136
                 URL: https://issues.apache.org/jira/browse/XGC-136
             Project: XMLGraphicsCommons
          Issue Type: Bug
            Reporter: Nicholas Moser
         Attachments: broken.png

Our team has a test PNG that we use in test cases that would fail fast in 
xmlgraphics-commons 2.7: 
[https://gist.github.com/NicholasMoser/ba8cef937cc3c0328ec89883f5c7879e]

After upgrading to 2.8, we noticed that it would fail with OOM: 
[https://gist.github.com/NicholasMoser/324ee1b814a6785a465fca2ee8e73c9c]

Apparently it no longer fails when parsing the header and now instead tries to 
allocate massive invalid chunks (0x2FC57D50 bytes). As far as I'm aware, this 
chunk size is valid per the PNG spec (0 - 2,147,483,647 bytes). The only caveat 
here is that the full image size is 0x50 bytes. Hypothetically this could be 
used as a denial of service vector that is small but becomes large in memory, 
kind of like a zip bomb.

The only reasonable fix I could see here would be to validate that chunk size 
is less than the total file size, as I cannot imagine a scenario where that 
would be valid. With that being said, I'm sure there are a lot of different 
ways to craft images that error in similar ways, so I'm not sure this is worth 
fixing.

Just curious to hear what contributors think.
{code:java}
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageInputStream;
import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSource;
import org.apache.xmlgraphics.image.loader.impl.PreloaderRawPNG;
import org.junit.jupiter.api.Test;

@Test
public void testBrokenPNG() throws Exception {
  try (InputStream is = Files.newInputStream(Paths.get("broken.png"))) {
    ImageInputStream iis = ImageIO.createImageInputStream(is);
    ImageSource imageSource = new ImageSource(iis, "", false);
    PreloaderRawPNG preloader = new PreloaderRawPNG();
    ImageContext imageContext = () -> 72.0f;
    // Fails with OOM
    ImageInfo imageInfo = preloader.preloadImage("", imageSource, imageContext);
  }
} {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to