From 2e6bedf937c7fd62a044d873422561d9b1e2e245 Mon Sep 17 00:00:00 2001
From: Leon Scroggins III <scroggo@google.com>
Date: Tue, 11 Feb 2020 16:31:21 -0500
Subject: [PATCH] AImageDecoder: Make create enforce int32_t dimensions

Bug: 135133301
Test: AImageDecoderTest

AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure at
creation time that the actual image dimensions will fit in int32_t.

In today's code, this should almost never happen:
- PNGs have their dimensions limited to 1000000
  - see PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX in pnglibconf.h
- JPEGs are limited to 65500
  - see JPEG_MAX_DIMENSION in jmorecfg.h
- WebPs' dimensions are encoded in 14 bits
- GIFs' dimensions are encoded in 16 bits
- SkBmpCodec and SkWbmpCodec require dimensions to fit in 16 bits
- SkIcoCodec uses SkBmpCodec or SkPngCodec, so their limits are
  enforced
- libheif limits to a size smaller than int32_t

It might be possible for a DNG image to be larger, and some of the above
are configurable. Just in case, make AImageDecoder_create fail on such a
large image.

Change-Id: Id520dfbc0581f990c4f52cb6675e987bf71c558c
---
 native/graphics/jni/imagedecoder.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index c1143ce9c3dc..86452357c3c3 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -28,6 +28,7 @@
 #include <utils/Color.h>
 
 #include <fcntl.h>
+#include <limits>
 #include <optional>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -70,6 +71,14 @@ static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDe
         return ResultToErrorCode(result);
     }
 
+    // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
+    // the conversion is safe.
+    const auto& info = androidCodec->getInfo();
+    if (info.width() > std::numeric_limits<int32_t>::max()
+        || info.height() > std::numeric_limits<int32_t>::max()) {
+        return ANDROID_IMAGE_DECODER_INVALID_INPUT;
+    }
+
     *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
     return ANDROID_IMAGE_DECODER_SUCCESS;
 }
-- 
GitLab