Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(804)

Side by Side Diff: third_party/WebKit/Source/core/frame/ImageBitmap.cpp

Issue 2249853008: Reject createImageBitmap promise when the cropRect or resize is too big (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/frame/ImageBitmap.h" 5 #include "core/frame/ImageBitmap.h"
6 6
7 #include "core/html/HTMLCanvasElement.h" 7 #include "core/html/HTMLCanvasElement.h"
8 #include "core/html/HTMLVideoElement.h" 8 #include "core/html/HTMLVideoElement.h"
9 #include "core/html/ImageData.h" 9 #include "core/html/ImageData.h"
10 #include "platform/graphics/AcceleratedStaticBitmapImage.h" 10 #include "platform/graphics/AcceleratedStaticBitmapImage.h"
11 #include "platform/graphics/skia/SkiaUtils.h" 11 #include "platform/graphics/skia/SkiaUtils.h"
12 #include "platform/image-decoders/ImageDecoder.h" 12 #include "platform/image-decoders/ImageDecoder.h"
13 #include "third_party/skia/include/core/SkCanvas.h" 13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkSurface.h" 14 #include "third_party/skia/include/core/SkSurface.h"
15 #include "wtf/CheckedNumeric.h"
15 #include "wtf/PtrUtil.h" 16 #include "wtf/PtrUtil.h"
16 #include "wtf/RefPtr.h" 17 #include "wtf/RefPtr.h"
17 #include <memory> 18 #include <memory>
18 19
19 namespace blink { 20 namespace blink {
20 21
21 static const char* imageOrientationFlipY = "flipY"; 22 static const char* imageOrientationFlipY = "flipY";
22 static const char* imageBitmapOptionNone = "none"; 23 static const char* imageBitmapOptionNone = "none";
23 24
24 namespace { 25 namespace {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 parsedOptions.resizeQuality = kHigh_SkFilterQuality; 95 parsedOptions.resizeQuality = kHigh_SkFilterQuality;
95 else if (options.resizeQuality() == "medium") 96 else if (options.resizeQuality() == "medium")
96 parsedOptions.resizeQuality = kMedium_SkFilterQuality; 97 parsedOptions.resizeQuality = kMedium_SkFilterQuality;
97 else if (options.resizeQuality() == "pixelated") 98 else if (options.resizeQuality() == "pixelated")
98 parsedOptions.resizeQuality = kNone_SkFilterQuality; 99 parsedOptions.resizeQuality = kNone_SkFilterQuality;
99 else 100 else
100 parsedOptions.resizeQuality = kLow_SkFilterQuality; 101 parsedOptions.resizeQuality = kLow_SkFilterQuality;
101 return parsedOptions; 102 return parsedOptions;
102 } 103 }
103 104
105 bool couldDstSizeOverflow(int width, int height)
Justin Novosad 2016/08/18 16:42:14 DstBufferSizeHasOverflow
xidachen 2016/08/22 12:02:28 Done.
106 {
107 CheckedNumeric<int> totalBytes = width;
Justin Novosad 2016/08/18 16:42:14 Why int and not size_t? If there is code somewhere
xidachen 2016/08/22 12:02:28 Done.
108 totalBytes *= height;
109 if (!totalBytes.IsValid())
Justin Novosad 2016/08/18 16:42:14 This one is not necessary. Just check is Valid at
xidachen 2016/08/22 12:02:28 Done.
110 return true;
111 totalBytes *= 4;
Justin Novosad 2016/08/18 16:42:14 This hardcoded 4 is dangerous. We will soon suppor
xidachen 2016/08/22 12:02:28 Done.
112 if (!totalBytes.IsValid())
113 return true;
114 return false;
115 }
116
104 } // namespace 117 } // namespace
105 118
106 static std::unique_ptr<uint8_t[]> copySkImageData(SkImage* input, const SkImageI nfo& info) 119 static std::unique_ptr<uint8_t[]> copySkImageData(SkImage* input, const SkImageI nfo& info)
107 { 120 {
108 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[input->wi dth() * input->height() * info.bytesPerPixel()]); 121 std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[input->wi dth() * input->height() * info.bytesPerPixel()]);
109 input->readPixels(info, dstPixels.get(), input->width() * info.bytesPerPixel (), 0, 0); 122 input->readPixels(info, dstPixels.get(), input->width() * info.bytesPerPixel (), 0, 0);
110 return dstPixels; 123 return dstPixels;
111 } 124 }
112 125
113 static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, std::un ique_ptr<uint8_t[]> imagePixels, int imageRowBytes) 126 static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, std::un ique_ptr<uint8_t[]> imagePixels, int imageRowBytes)
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et())); 295 return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.g et()));
283 return StaticBitmapImage::create(skiaImage.release()); 296 return StaticBitmapImage::create(skiaImage.release());
284 } 297 }
285 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); 298 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get()));
286 } 299 }
287 300
288 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do cument* document, const ImageBitmapOptions& options) 301 ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do cument* document, const ImageBitmapOptions& options)
289 { 302 {
290 RefPtr<Image> input = image->cachedImage()->getImage(); 303 RefPtr<Image> input = image->cachedImage()->getImage();
291 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS ourceSize()); 304 ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapS ourceSize());
305 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
Justin Novosad 2016/08/18 16:42:14 This repeated bit of code could be made simpler if
xidachen 2016/08/22 12:02:28 Moving the check to the place where overflow occur
306 return;
307 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
308 return;
292 309
293 if (options.colorSpaceConversion() == "none") 310 if (options.colorSpaceConversion() == "none")
294 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD ecoder::GammaAndColorProfileIgnored); 311 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD ecoder::GammaAndColorProfileIgnored);
295 else 312 else
296 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD ecoder::GammaAndColorProfileApplied); 313 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageD ecoder::GammaAndColorProfileApplied);
297 if (!m_image) 314 if (!m_image)
298 return; 315 return;
299 // In the case where the source image is lazy-decoded, m_image may not be in 316 // In the case where the source image is lazy-decoded, m_image may not be in
300 // a decoded state, we trigger it here. 317 // a decoded state, we trigger it here.
301 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame(); 318 RefPtr<SkImage> skImage = m_image->imageForCurrentFrame();
302 SkPixmap pixmap; 319 SkPixmap pixmap;
303 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { 320 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) {
304 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height()); 321 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(skImage->width (), skImage->height());
305 surface->getCanvas()->drawImage(skImage.get(), 0, 0); 322 surface->getCanvas()->drawImage(skImage.get(), 0, 0);
306 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( ))); 323 m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot( )));
307 } 324 }
308 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ())); 325 m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin ()));
309 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); 326 m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
310 } 327 }
311 328
312 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do cument* document, const ImageBitmapOptions& options) 329 ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do cument* document, const ImageBitmapOptions& options)
313 { 330 {
314 IntSize playerSize; 331 IntSize playerSize;
315 if (video->webMediaPlayer()) 332 if (video->webMediaPlayer())
316 playerSize = video->webMediaPlayer()->naturalSize(); 333 playerSize = video->webMediaPlayer()->naturalSize();
317 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS ourceSize()); 334 ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapS ourceSize());
335 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
336 return;
337 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
338 return;
318 339
319 IntRect videoRect = IntRect(IntPoint(), playerSize); 340 IntRect videoRect = IntRect(IntPoint(), playerSize);
320 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); 341 IntRect srcRect = intersection(parsedOptions.cropRect, videoRect);
321 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix els); 342 std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(IntSize(parsedOpti ons.resizeWidth, parsedOptions.resizeHeight), NonOpaque, DoNotInitializeImagePix els);
322 if (!buffer) 343 if (!buffer)
323 return; 344 return;
324 345
325 if (parsedOptions.flipY) { 346 if (parsedOptions.flipY) {
326 buffer->canvas()->translate(0, buffer->size().height()); 347 buffer->canvas()->translate(0, buffer->size().height());
327 buffer->canvas()->scale(1, -1); 348 buffer->canvas()->scale(1, -1);
(...skipping 16 matching lines...) Expand all
344 m_image = StaticBitmapImage::create(skiaImage.release()); 365 m_image = StaticBitmapImage::create(skiaImage.release());
345 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ())); 366 m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin ()));
346 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); 367 m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
347 } 368 }
348 369
349 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, const ImageBitmapOptions& options) 370 ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, const ImageBitmapOptions& options)
350 { 371 {
351 ASSERT(canvas->isPaintable()); 372 ASSERT(canvas->isPaintable());
352 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); 373 RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration);
353 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap SourceSize()); 374 ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmap SourceSize());
375 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
376 return;
377 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
378 return;
354 379
355 bool isPremultiplyAlphaReverted = false; 380 bool isPremultiplyAlphaReverted = false;
356 if (!parsedOptions.premultiplyAlpha) { 381 if (!parsedOptions.premultiplyAlpha) {
357 parsedOptions.premultiplyAlpha = true; 382 parsedOptions.premultiplyAlpha = true;
358 isPremultiplyAlphaReverted = true; 383 isPremultiplyAlphaReverted = true;
359 } 384 }
360 m_image = cropImage(input.get(), parsedOptions); 385 m_image = cropImage(input.get(), parsedOptions);
361 if (!m_image) 386 if (!m_image)
362 return; 387 return;
363 if (isPremultiplyAlphaReverted) { 388 if (isPremultiplyAlphaReverted) {
(...skipping 22 matching lines...) Expand all
386 { 411 {
387 delete[] static_cast<const uint8_t*>(pixels); 412 delete[] static_cast<const uint8_t*>(pixels);
388 }, nullptr)); 413 }, nullptr));
389 } 414 }
390 415
391 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag eBitmapOptions& options) 416 ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag eBitmapOptions& options)
392 { 417 {
393 // TODO(xidachen): implement the resize option 418 // TODO(xidachen): implement the resize option
394 IntRect dataSrcRect = IntRect(IntPoint(), data->size()); 419 IntRect dataSrcRect = IntRect(IntPoint(), data->size());
395 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo urceSize()); 420 ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSo urceSize());
421 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
422 return;
423 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
424 return;
396 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec t) : dataSrcRect; 425 IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRec t) : dataSrcRect;
397 426
398 // treat non-premultiplyAlpha as a special case 427 // treat non-premultiplyAlpha as a special case
399 if (!parsedOptions.premultiplyAlpha) { 428 if (!parsedOptions.premultiplyAlpha) {
400 unsigned char* srcAddr = data->data()->data(); 429 unsigned char* srcAddr = data->data()->data();
401 int srcHeight = data->size().height(); 430 int srcHeight = data->size().height();
402 int dstHeight = parsedOptions.cropRect.height(); 431 int dstHeight = parsedOptions.cropRect.height();
403 432
404 // Using kN32 type, swizzle input if necessary. 433 // Using kN32 type, swizzle input if necessary.
405 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst Height, kN32_SkColorType, kUnpremul_SkAlphaType); 434 SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dst Height, kN32_SkColorType, kUnpremul_SkAlphaType);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 } 514 }
486 m_image = StaticBitmapImage::create(skImage); 515 m_image = StaticBitmapImage::create(skImage);
487 } 516 }
488 517
489 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options) 518 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const ImageBitmapOptions& options)
490 { 519 {
491 RefPtr<Image> input = bitmap->bitmapImage(); 520 RefPtr<Image> input = bitmap->bitmapImage();
492 if (!input) 521 if (!input)
493 return; 522 return;
494 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ; 523 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ;
524 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
525 return;
526 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
527 return;
495 528
496 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); 529 m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha);
497 if (!m_image) 530 if (!m_image)
498 return; 531 return;
499 m_image->setOriginClean(bitmap->originClean()); 532 m_image->setOriginClean(bitmap->originClean());
500 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); 533 m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
501 } 534 }
502 535
503 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect> cropRect, const ImageBitmapOptions& options) 536 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect> cropRect, const ImageBitmapOptions& options)
504 { 537 {
505 bool originClean = image->originClean(); 538 bool originClean = image->originClean();
506 RefPtr<Image> input = image; 539 RefPtr<Image> input = image;
507 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ; 540 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()) ;
541 if (couldDstSizeOverflow(parsedOptions.cropRect.width(), parsedOptions.cropR ect.height()))
542 return;
543 if (parsedOptions.shouldScaleInput && couldDstSizeOverflow(parsedOptions.res izeWidth, parsedOptions.resizeHeight))
544 return;
508 545
509 m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); 546 m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha);
510 if (!m_image) 547 if (!m_image)
511 return; 548 return;
512 m_image->setOriginClean(originClean); 549 m_image->setOriginClean(originClean);
513 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); 550 m_image->setPremultiplied(parsedOptions.premultiplyAlpha);
514 } 551 }
515 552
516 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) 553 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image)
517 { 554 {
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 FloatSize ImageBitmap::elementSize(const FloatSize&) const 689 FloatSize ImageBitmap::elementSize(const FloatSize&) const
653 { 690 {
654 return FloatSize(width(), height()); 691 return FloatSize(width(), height());
655 } 692 }
656 693
657 DEFINE_TRACE(ImageBitmap) 694 DEFINE_TRACE(ImageBitmap)
658 { 695 {
659 } 696 }
660 697
661 } // namespace blink 698 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698