Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34926e40 authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android Build Coastguard Worker
Browse files

Enforce a hard limit for the size of images to be decoded

Although standards like JPEG allow for sizes as large as
65,535×65,535 pixels, we realistically cannot fit such large images in
memory.

Created a test gif since it's the smallest format I could find. It's
larger than strictly necessary for the test in case we want to increase
the hard limit in the future.

Bug: 444671303
Test: manually verified that a notification that causes a crashloop
without this change, doesn't anymore
Test: LocalImageResolverTest
Flag: EXEMPT CVE_FIX

(cherry picked from commit 449f35b532d5f680b90c8f9d8150010e7f5f30df)
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:a9d42aa0f960c459c0dd5eb11c185963b6633109
Merged-In: I0c95cfeabe169630286e7af8577c4495c2b1015f
Change-Id: I0c95cfeabe169630286e7af8577c4495c2b1015f
parent 527b25ca
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -46,6 +46,12 @@ public class LocalImageResolver {
    @VisibleForTesting
    static final int DEFAULT_MAX_SAFE_ICON_SIZE_PX = 480;

    /**
     * If an image is larger than this, we won't even attempt to decode it, as we risk taking up all
     * of the device memory.
     */
    private static final int DEFAULT_DECODE_HARD_LIMIT_PX = 4096;

    /**
     * Resolve an image from the given Uri using {@link ImageDecoder} if it contains a
     * bitmap reference.
@@ -249,6 +255,16 @@ public class LocalImageResolver {
    private static void onHeaderDecoded(ImageDecoder decoder, ImageDecoder.ImageInfo info,
            int maxWidth, int maxHeight) {
        final Size size = info.getSize();

        if (size.getWidth() > DEFAULT_DECODE_HARD_LIMIT_PX
                || size.getHeight() > DEFAULT_DECODE_HARD_LIMIT_PX) {
            // The image is larger than what we can reasonably expect to decode without filling up
            // the device memory, so let's bail.
            throw new RuntimeException(
                    "Image dimensions (" + size.getWidth() + "x" + size.getHeight()
                            + ") exceed the maximum allowed size.");
        }

        final int originalSize = Math.max(size.getHeight(), size.getWidth());
        final int maxSize = Math.max(maxWidth, maxHeight);
        final double ratio = (originalSize > maxSize)
+186 KiB
Loading image diff...
+8 −0
Original line number Diff line number Diff line
@@ -282,6 +282,14 @@ public class LocalImageResolverTest {
        assertThat(d).isNull();
    }

    @Test(expected = IOException.class)
    public void resolveImage_veryLargeResource_throwsException() throws IOException {
        // Passing in an unreasonably large image should throw an exception.
        Uri uri = Uri.parse("android.resource://"
                + mContext.getPackageName() + "/" + R.drawable.test16000x16000);
        LocalImageResolver.resolveImage(uri, mContext);
    }

    @Test
    public void resolveResourcesForIcon_notAResourceIcon_returnsNull() {
        Icon icon = Icon.createWithContentUri(Uri.parse("some_uri"));