Resource size hints appear to be used incorrectly in JPMS

Luke Hutchison luke.hutch at gmail.com
Wed Aug 8 05:19:06 UTC 2018


The uncompressed size of a resource is used in
BasicImageReader#getResource(ImageLocation), which calls readBuffer(offset,
uncompressedSize) .  The readBuffer method then does two or three things
that seem incorrect if the size is obtained from ZipEntry#getSize():

(1) size < 0 is rejected, but ZipEntry#getSize() returns "the uncompressed
size of the entry data, or -1 if not known":

        if (size < 0 || Integer.MAX_VALUE <= size) {
            throw new IndexOutOfBoundsException("Bad size: " + size);
        }

(2) size is used directly without restriction, rather than as a size hint.
ZipEntry#getSize() may actually return a totally bogus value (you can write
anything you want for the uncompressed size in a zipfile entry). If the
requested size is large, e.g. something close to Integer.MAX_VALUE, large
allocations will occur every time a resource is read, which can be used as
a memory allocation attack vector.

            ByteBuffer buffer = slice(memoryMap, (int)offset, (int)size);
            // ...
            ByteBuffer buffer = ImageBufferCache.getBuffer(size);

Instead, the initial buffer size should be set to something like
Math.min(16 * 1024 * 1024, size), and then grown as needed if the resource
is indeed larger than this initial allocation.

(3) The BasicImageReader#readBuffer(long offset, long size) checks if the
filesize is larger than Integer.MAX_VALUE. However, InputStream contains
the following max limit for byte array sizes:

    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;

If this limit applies to ByteBuffers (and it does apply to ByteBuffers if
they are array-backed), then the check of size against Integer.MAX_VALUE is
incorrect.


More information about the jigsaw-dev mailing list