Commit 36a5933a authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[imagedata] Handle invalid-size case in getImageData

StaticBitmapImage returned 0 to indicate an invalid image size (e.g.
integer overflow). This case was not handled properly by the caller.
With this CL we add handling for the 0-case and throw an exception.

R=jbroman@chromium.org

Bug: chromium:1027522
Change-Id: I755ea7b3e9c50a73d20487397d9862f3ca67dd74
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1932441
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719197}
parent ffeae8e3
...@@ -263,10 +263,12 @@ static bool ExtractImageData(Image* image, ...@@ -263,10 +263,12 @@ static bool ExtractImageData(Image* image,
kDoNotRespectImageOrientation, kDoNotRespectImageOrientation,
Image::kDoNotClampImageToSourceRect, Image::kSyncDecode); Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
size_t size_in_bytes = size_t size_in_bytes;
StaticBitmapImage::GetSizeInBytes(image_dest_rect, color_params); if (!StaticBitmapImage::GetSizeInBytes(image_dest_rect, color_params)
if (size_in_bytes > v8::TypedArray::kMaxLength) .AssignIfValid(&size_in_bytes) ||
size_in_bytes > v8::TypedArray::kMaxLength) {
return false; return false;
}
ArrayBufferContents result(size_in_bytes, 1, ArrayBufferContents::kNotShared, ArrayBufferContents result(size_in_bytes, 1, ArrayBufferContents::kNotShared,
ArrayBufferContents::kZeroInitialize); ArrayBufferContents::kZeroInitialize);
if (result.DataLength() != size_in_bytes) if (result.DataLength() != size_in_bytes)
......
...@@ -1588,10 +1588,13 @@ ImageData* BaseRenderingContext2D::getImageData( ...@@ -1588,10 +1588,13 @@ ImageData* BaseRenderingContext2D::getImageData(
if (IsAccelerated()) if (IsAccelerated())
DisableAcceleration(); DisableAcceleration();
size_t size_in_bytes = size_t size_in_bytes;
StaticBitmapImage::GetSizeInBytes(image_data_rect, color_params); if (!StaticBitmapImage::GetSizeInBytes(image_data_rect, color_params)
if (size_in_bytes > v8::TypedArray::kMaxLength) .AssignIfValid(&size_in_bytes) ||
size_in_bytes > v8::TypedArray::kMaxLength) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr; return nullptr;
}
bool may_have_stray_area = bool may_have_stray_area =
IsAccelerated() // GPU readback may fail silently. IsAccelerated() // GPU readback may fail silently.
......
...@@ -69,13 +69,13 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace( ...@@ -69,13 +69,13 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
return UnacceleratedStaticBitmapImage::Create(skia_image); return UnacceleratedStaticBitmapImage::Create(skia_image);
} }
size_t StaticBitmapImage::GetSizeInBytes( base::CheckedNumeric<size_t> StaticBitmapImage::GetSizeInBytes(
const IntRect& rect, const IntRect& rect,
const CanvasColorParams& color_params) { const CanvasColorParams& color_params) {
uint8_t bytes_per_pixel = color_params.BytesPerPixel(); uint8_t bytes_per_pixel = color_params.BytesPerPixel();
base::CheckedNumeric<size_t> data_size = bytes_per_pixel; base::CheckedNumeric<size_t> data_size = bytes_per_pixel;
data_size *= rect.Size().Area(); data_size *= rect.Size().Area();
return data_size.ValueOrDefault(0); return data_size;
} }
bool StaticBitmapImage::MayHaveStrayArea( bool StaticBitmapImage::MayHaveStrayArea(
...@@ -94,7 +94,7 @@ bool StaticBitmapImage::CopyToByteArray( ...@@ -94,7 +94,7 @@ bool StaticBitmapImage::CopyToByteArray(
base::span<uint8_t> dst, base::span<uint8_t> dst,
const IntRect& rect, const IntRect& rect,
const CanvasColorParams& color_params) { const CanvasColorParams& color_params) {
DCHECK_EQ(dst.size(), GetSizeInBytes(rect, color_params)); DCHECK_EQ(dst.size(), GetSizeInBytes(rect, color_params).ValueOrDie());
if (!src_image) if (!src_image)
return true; return true;
......
...@@ -100,8 +100,9 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image { ...@@ -100,8 +100,9 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
sk_sp<SkColorSpace>, sk_sp<SkColorSpace>,
SkColorType = kN32_SkColorType); SkColorType = kN32_SkColorType);
static size_t GetSizeInBytes(const IntRect& rect, static base::CheckedNumeric<size_t> GetSizeInBytes(
const CanvasColorParams& color_params); const IntRect& rect,
const CanvasColorParams& color_params);
static bool MayHaveStrayArea(scoped_refptr<StaticBitmapImage> src_image, static bool MayHaveStrayArea(scoped_refptr<StaticBitmapImage> src_image,
const IntRect& rect); const IntRect& rect);
......
...@@ -27,9 +27,9 @@ TEST_F(StaticBitmapImageTest, ...@@ -27,9 +27,9 @@ TEST_F(StaticBitmapImageTest,
IntRect too_big_rect(IntPoint(0, 0), IntRect too_big_rect(IntPoint(0, 0),
IntSize(1, (v8::TypedArray::kMaxLength / 4) + 1)); IntSize(1, (v8::TypedArray::kMaxLength / 4) + 1));
EXPECT_GT( EXPECT_GT(StaticBitmapImage::GetSizeInBytes(too_big_rect, CanvasColorParams())
StaticBitmapImage::GetSizeInBytes(too_big_rect, CanvasColorParams()), .ValueOrDie(),
v8::TypedArray::kMaxLength); v8::TypedArray::kMaxLength);
} }
} // namespace blink } // namespace blink
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
test(() => { test(() => {
let C = document.getElementById("canvas1"); let C = document.getElementById("canvas1");
let Z = C.getContext("2d"); let Z = C.getContext("2d");
Z.getImageData(174.696924716, -3.94829667221, 6.80556775521, 291126556.736); assert_throws(new RangeError(), () => Z.getImageData(174.696924716,
-3.94829667221, 6.80556775521, 291126556.736));
}, "Regression test for https://crbug.com/1017918."); }, "Regression test for https://crbug.com/1017918.");
</script> </script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment