From f3f1ed4efaf0c97b7c2b163449be23f74de07806 Mon Sep 17 00:00:00 2001 From: Seth Fowler Date: Thu, 23 Jun 2016 11:13:14 -0700 Subject: [PATCH] Bug 1262549 - Refuse to allocate huge deinterlacing buffers. r=edwin --- image/SurfaceFilters.h | 9 +++ image/test/gtest/TestDecodeToSurface.cpp | 39 ++++----- image/test/gtest/TestDecoders.cpp | 81 ++++++++++--------- image/test/gtest/TestDeinterlacingFilter.cpp | 43 ++++++---- image/test/gtest/TestMetadata.cpp | 57 ++++++------- .../test/gtest/TestSurfacePipeIntegration.cpp | 48 ++++++++--- 6 files changed, 165 insertions(+), 112 deletions(-) diff --git a/image/SurfaceFilters.h b/image/SurfaceFilters.h index ae1347b66698..23240acacb51 100644 --- a/image/SurfaceFilters.h +++ b/image/SurfaceFilters.h @@ -21,6 +21,7 @@ #include "mozilla/gfx/2D.h" #include "DownscalingFilter.h" +#include "SurfaceCache.h" #include "SurfacePipe.h" namespace mozilla { @@ -91,6 +92,14 @@ public: outputSize.height * sizeof(PixelType); + // Use the size of the SurfaceCache as a heuristic to avoid gigantic + // allocations. Even if DownscalingFilter allowed us to allocate space for + // the output image, the deinterlacing buffer may still be too big, and + // fallible allocation won't always save us in the presence of overcommit. + if (!SurfaceCache::CanHold(bufferSize)) { + return NS_ERROR_OUT_OF_MEMORY; + } + // Allocate the buffer, which contains deinterlaced scanlines of the image. // The buffer is necessary so that we can output rows which have already // been deinterlaced again on subsequent passes. Since a later stage in the diff --git a/image/test/gtest/TestDecodeToSurface.cpp b/image/test/gtest/TestDecodeToSurface.cpp index dc688a4a0c0d..fd1716e5a759 100644 --- a/image/test/gtest/TestDecodeToSurface.cpp +++ b/image/test/gtest/TestDecodeToSurface.cpp @@ -22,16 +22,6 @@ using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::image; -TEST(ImageDecodeToSurface, ImageModuleAvailable) -{ - // We can run into problems if XPCOM modules get initialized in the wrong - // order. It's important that this test run first, both as a sanity check and - // to ensure we get the module initialization order we want. - nsCOMPtr imgTools = - do_CreateInstance("@mozilla.org/image/tools;1"); - EXPECT_TRUE(imgTools != nullptr); -} - class DecodeToSurfaceRunnable : public Runnable { public: @@ -95,24 +85,35 @@ RunDecodeToSurface(const ImageTestCase& aTestCase) surface = nullptr; } -TEST(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); } -TEST(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); } -TEST(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); } -TEST(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); } -TEST(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); } -TEST(ImageDecodeToSurface, Icon) { RunDecodeToSurface(GreenIconTestCase()); } +class ImageDecodeToSurface : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + // Ensure that ImageLib services are initialized. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + EXPECT_TRUE(imgTools != nullptr); + } +}; -TEST(ImageDecodeToSurface, AnimatedGIF) +TEST_F(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); } +TEST_F(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); } +TEST_F(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); } +TEST_F(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); } +TEST_F(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); } +TEST_F(ImageDecodeToSurface, Icon) { RunDecodeToSurface(GreenIconTestCase()); } + +TEST_F(ImageDecodeToSurface, AnimatedGIF) { RunDecodeToSurface(GreenFirstFrameAnimatedGIFTestCase()); } -TEST(ImageDecodeToSurface, AnimatedPNG) +TEST_F(ImageDecodeToSurface, AnimatedPNG) { RunDecodeToSurface(GreenFirstFrameAnimatedPNGTestCase()); } -TEST(ImageDecodeToSurface, Corrupt) +TEST_F(ImageDecodeToSurface, Corrupt) { ImageTestCase testCase = CorruptTestCase(); diff --git a/image/test/gtest/TestDecoders.cpp b/image/test/gtest/TestDecoders.cpp index 97adeb53870f..ff1ae5f561ae 100644 --- a/image/test/gtest/TestDecoders.cpp +++ b/image/test/gtest/TestDecoders.cpp @@ -28,16 +28,6 @@ using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::image; -TEST(ImageDecoders, ImageModuleAvailable) -{ - // We can run into problems if XPCOM modules get initialized in the wrong - // order. It's important that this test run first, both as a sanity check and - // to ensure we get the module initialization order we want. - nsCOMPtr imgTools = - do_CreateInstance("@mozilla.org/image/tools;1"); - EXPECT_TRUE(imgTools != nullptr); -} - static already_AddRefed CheckDecoderState(const ImageTestCase& aTestCase, Decoder* aDecoder) { @@ -225,152 +215,163 @@ CheckDownscaleDuringDecode(const ImageTestCase& aTestCase) }); } -TEST(ImageDecoders, PNGSingleChunk) +class ImageDecoders : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + // Ensure that ImageLib services are initialized. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + EXPECT_TRUE(imgTools != nullptr); + } +}; + +TEST_F(ImageDecoders, PNGSingleChunk) { CheckDecoderSingleChunk(GreenPNGTestCase()); } -TEST(ImageDecoders, PNGMultiChunk) +TEST_F(ImageDecoders, PNGMultiChunk) { CheckDecoderMultiChunk(GreenPNGTestCase()); } -TEST(ImageDecoders, PNGDownscaleDuringDecode) +TEST_F(ImageDecoders, PNGDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledPNGTestCase()); } -TEST(ImageDecoders, GIFSingleChunk) +TEST_F(ImageDecoders, GIFSingleChunk) { CheckDecoderSingleChunk(GreenGIFTestCase()); } -TEST(ImageDecoders, GIFMultiChunk) +TEST_F(ImageDecoders, GIFMultiChunk) { CheckDecoderMultiChunk(GreenGIFTestCase()); } -TEST(ImageDecoders, GIFDownscaleDuringDecode) +TEST_F(ImageDecoders, GIFDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledGIFTestCase()); } -TEST(ImageDecoders, JPGSingleChunk) +TEST_F(ImageDecoders, JPGSingleChunk) { CheckDecoderSingleChunk(GreenJPGTestCase()); } -TEST(ImageDecoders, JPGMultiChunk) +TEST_F(ImageDecoders, JPGMultiChunk) { CheckDecoderMultiChunk(GreenJPGTestCase()); } -TEST(ImageDecoders, JPGDownscaleDuringDecode) +TEST_F(ImageDecoders, JPGDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledJPGTestCase()); } -TEST(ImageDecoders, BMPSingleChunk) +TEST_F(ImageDecoders, BMPSingleChunk) { CheckDecoderSingleChunk(GreenBMPTestCase()); } -TEST(ImageDecoders, BMPMultiChunk) +TEST_F(ImageDecoders, BMPMultiChunk) { CheckDecoderMultiChunk(GreenBMPTestCase()); } -TEST(ImageDecoders, BMPDownscaleDuringDecode) +TEST_F(ImageDecoders, BMPDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledBMPTestCase()); } -TEST(ImageDecoders, ICOSingleChunk) +TEST_F(ImageDecoders, ICOSingleChunk) { CheckDecoderSingleChunk(GreenICOTestCase()); } -TEST(ImageDecoders, ICOMultiChunk) +TEST_F(ImageDecoders, ICOMultiChunk) { CheckDecoderMultiChunk(GreenICOTestCase()); } -TEST(ImageDecoders, ICODownscaleDuringDecode) +TEST_F(ImageDecoders, ICODownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledICOTestCase()); } -TEST(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) +TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase()); } -TEST(ImageDecoders, IconSingleChunk) +TEST_F(ImageDecoders, IconSingleChunk) { CheckDecoderSingleChunk(GreenIconTestCase()); } -TEST(ImageDecoders, IconMultiChunk) +TEST_F(ImageDecoders, IconMultiChunk) { CheckDecoderMultiChunk(GreenIconTestCase()); } -TEST(ImageDecoders, IconDownscaleDuringDecode) +TEST_F(ImageDecoders, IconDownscaleDuringDecode) { CheckDownscaleDuringDecode(DownscaledIconTestCase()); } -TEST(ImageDecoders, AnimatedGIFSingleChunk) +TEST_F(ImageDecoders, AnimatedGIFSingleChunk) { CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase()); } -TEST(ImageDecoders, AnimatedGIFMultiChunk) +TEST_F(ImageDecoders, AnimatedGIFMultiChunk) { CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase()); } -TEST(ImageDecoders, AnimatedPNGSingleChunk) +TEST_F(ImageDecoders, AnimatedPNGSingleChunk) { CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase()); } -TEST(ImageDecoders, AnimatedPNGMultiChunk) +TEST_F(ImageDecoders, AnimatedPNGMultiChunk) { CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase()); } -TEST(ImageDecoders, CorruptSingleChunk) +TEST_F(ImageDecoders, CorruptSingleChunk) { CheckDecoderSingleChunk(CorruptTestCase()); } -TEST(ImageDecoders, CorruptMultiChunk) +TEST_F(ImageDecoders, CorruptMultiChunk) { CheckDecoderMultiChunk(CorruptTestCase()); } -TEST(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) +TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) { CheckDecoderSingleChunk(CorruptICOWithBadBMPWidthTestCase()); } -TEST(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) +TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) { CheckDecoderMultiChunk(CorruptICOWithBadBMPWidthTestCase()); } -TEST(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) +TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) { CheckDecoderSingleChunk(CorruptICOWithBadBMPHeightTestCase()); } -TEST(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) +TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) { CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase()); } -TEST(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) +TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) { ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase(); diff --git a/image/test/gtest/TestDeinterlacingFilter.cpp b/image/test/gtest/TestDeinterlacingFilter.cpp index 344434aba5f2..9707ebb3c870 100644 --- a/image/test/gtest/TestDeinterlacingFilter.cpp +++ b/image/test/gtest/TestDeinterlacingFilter.cpp @@ -59,7 +59,18 @@ AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize) SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageDeinterlacingFilter, WritePixels100_100) +class ImageDeinterlacingFilter : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + // Ensure that ImageLib services are initialized. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + EXPECT_TRUE(imgTools != nullptr); + } +}; + +TEST_F(ImageDeinterlacingFilter, WritePixels100_100) { WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -69,7 +80,7 @@ TEST(ImageDeinterlacingFilter, WritePixels100_100) }); } -TEST(ImageDeinterlacingFilter, WritePixels99_99) +TEST_F(ImageDeinterlacingFilter, WritePixels99_99) { WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -79,7 +90,7 @@ TEST(ImageDeinterlacingFilter, WritePixels99_99) }); } -TEST(ImageDeinterlacingFilter, WritePixels8_8) +TEST_F(ImageDeinterlacingFilter, WritePixels8_8) { WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -89,7 +100,7 @@ TEST(ImageDeinterlacingFilter, WritePixels8_8) }); } -TEST(ImageDeinterlacingFilter, WritePixels7_7) +TEST_F(ImageDeinterlacingFilter, WritePixels7_7) { WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -99,7 +110,7 @@ TEST(ImageDeinterlacingFilter, WritePixels7_7) }); } -TEST(ImageDeinterlacingFilter, WritePixels3_3) +TEST_F(ImageDeinterlacingFilter, WritePixels3_3) { WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -109,7 +120,7 @@ TEST(ImageDeinterlacingFilter, WritePixels3_3) }); } -TEST(ImageDeinterlacingFilter, WritePixels1_1) +TEST_F(ImageDeinterlacingFilter, WritePixels1_1) { WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -119,7 +130,7 @@ TEST(ImageDeinterlacingFilter, WritePixels1_1) }); } -TEST(ImageDeinterlacingFilter, PalettedWritePixels) +TEST_F(ImageDeinterlacingFilter, PalettedWritePixels) { WithPalettedDeinterlacingFilter(IntSize(100, 100), [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -127,7 +138,7 @@ TEST(ImageDeinterlacingFilter, PalettedWritePixels) }); } -TEST(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52) +TEST_F(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52) { WithDeinterlacingFilter(IntSize(51, 52), /* aProgressiveDisplay = */ false, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -233,7 +244,7 @@ TEST(ImageDeinterlacingFilter, WritePixelsNonProgressiveOutput51_52) }); } -TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20) +TEST_F(ImageDeinterlacingFilter, WritePixelsOutput20_20) { WithDeinterlacingFilter(IntSize(20, 20), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -307,7 +318,7 @@ TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20) }); } -TEST(ImageDeinterlacingFilter, WritePixelsOutput7_7) +TEST_F(ImageDeinterlacingFilter, WritePixelsOutput7_7) { WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -369,7 +380,7 @@ TEST(ImageDeinterlacingFilter, WritePixelsOutput7_7) }); } -TEST(ImageDeinterlacingFilter, WritePixelsOutput3_3) +TEST_F(ImageDeinterlacingFilter, WritePixelsOutput3_3) { WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -422,7 +433,7 @@ TEST(ImageDeinterlacingFilter, WritePixelsOutput3_3) }); } -TEST(ImageDeinterlacingFilter, WritePixelsOutput1_1) +TEST_F(ImageDeinterlacingFilter, WritePixelsOutput1_1) { WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -490,7 +501,7 @@ WriteRowAndCheckInterlacerOutput(Decoder* aDecoder, } } -TEST(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) +TEST_F(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) { WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -571,7 +582,7 @@ TEST(ImageDeinterlacingFilter, WritePixelsIntermediateOutput7_7) }); } -TEST(ImageDeinterlacingFilter, WritePixelsNonProgressiveIntermediateOutput7_7) +TEST_F(ImageDeinterlacingFilter, WritePixelsNonProgressiveIntermediateOutput7_7) { WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ false, [](Decoder* aDecoder, SurfaceFilter* aFilter) { @@ -653,13 +664,13 @@ TEST(ImageDeinterlacingFilter, WritePixelsNonProgressiveIntermediateOutput7_7) } -TEST(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0) +TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0) { // A 0x0 input size is invalid, so configuration should fail. AssertConfiguringDeinterlacingFilterFails(IntSize(0, 0)); } -TEST(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1) +TEST_F(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1) { // A negative input size is invalid, so configuration should fail. AssertConfiguringDeinterlacingFilterFails(IntSize(-1, -1)); diff --git a/image/test/gtest/TestMetadata.cpp b/image/test/gtest/TestMetadata.cpp index f20e26640e9a..b68db59a77b1 100644 --- a/image/test/gtest/TestMetadata.cpp +++ b/image/test/gtest/TestMetadata.cpp @@ -28,16 +28,6 @@ using namespace mozilla; using namespace mozilla::gfx; using namespace mozilla::image; -TEST(ImageMetadata, ImageModuleAvailable) -{ - // We can run into problems if XPCOM modules get initialized in the wrong - // order. It's important that this test run first, both as a sanity check and - // to ensure we get the module initialization order we want. - nsCOMPtr imgTools = - do_CreateInstance("@mozilla.org/image/tools;1"); - EXPECT_TRUE(imgTools != nullptr); -} - enum class BMPWithinICO { NO, @@ -140,53 +130,64 @@ CheckMetadata(const ImageTestCase& aTestCase, (fullProgress & FLAG_IS_ANIMATED)); } -TEST(ImageMetadata, PNG) { CheckMetadata(GreenPNGTestCase()); } -TEST(ImageMetadata, TransparentPNG) { CheckMetadata(TransparentPNGTestCase()); } -TEST(ImageMetadata, GIF) { CheckMetadata(GreenGIFTestCase()); } -TEST(ImageMetadata, TransparentGIF) { CheckMetadata(TransparentGIFTestCase()); } -TEST(ImageMetadata, JPG) { CheckMetadata(GreenJPGTestCase()); } -TEST(ImageMetadata, BMP) { CheckMetadata(GreenBMPTestCase()); } -TEST(ImageMetadata, ICO) { CheckMetadata(GreenICOTestCase()); } -TEST(ImageMetadata, Icon) { CheckMetadata(GreenIconTestCase()); } +class ImageDecoderMetadata : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + // Ensure that ImageLib services are initialized. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + EXPECT_TRUE(imgTools != nullptr); + } +}; -TEST(ImageMetadata, AnimatedGIF) +TEST_F(ImageDecoderMetadata, PNG) { CheckMetadata(GreenPNGTestCase()); } +TEST_F(ImageDecoderMetadata, TransparentPNG) { CheckMetadata(TransparentPNGTestCase()); } +TEST_F(ImageDecoderMetadata, GIF) { CheckMetadata(GreenGIFTestCase()); } +TEST_F(ImageDecoderMetadata, TransparentGIF) { CheckMetadata(TransparentGIFTestCase()); } +TEST_F(ImageDecoderMetadata, JPG) { CheckMetadata(GreenJPGTestCase()); } +TEST_F(ImageDecoderMetadata, BMP) { CheckMetadata(GreenBMPTestCase()); } +TEST_F(ImageDecoderMetadata, ICO) { CheckMetadata(GreenICOTestCase()); } +TEST_F(ImageDecoderMetadata, Icon) { CheckMetadata(GreenIconTestCase()); } + +TEST_F(ImageDecoderMetadata, AnimatedGIF) { CheckMetadata(GreenFirstFrameAnimatedGIFTestCase()); } -TEST(ImageMetadata, AnimatedPNG) +TEST_F(ImageDecoderMetadata, AnimatedPNG) { CheckMetadata(GreenFirstFrameAnimatedPNGTestCase()); } -TEST(ImageMetadata, FirstFramePaddingGIF) +TEST_F(ImageDecoderMetadata, FirstFramePaddingGIF) { CheckMetadata(FirstFramePaddingGIFTestCase()); } -TEST(ImageMetadata, TransparentIfWithinICOBMPNotWithinICO) +TEST_F(ImageDecoderMetadata, TransparentIfWithinICOBMPNotWithinICO) { CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_DEFAULT_FLAGS), BMPWithinICO::NO); } -TEST(ImageMetadata, TransparentIfWithinICOBMPWithinICO) +TEST_F(ImageDecoderMetadata, TransparentIfWithinICOBMPWithinICO) { CheckMetadata(TransparentIfWithinICOBMPTestCase(TEST_CASE_IS_TRANSPARENT), BMPWithinICO::YES); } -TEST(ImageMetadata, RLE4BMP) { CheckMetadata(RLE4BMPTestCase()); } -TEST(ImageMetadata, RLE8BMP) { CheckMetadata(RLE8BMPTestCase()); } +TEST_F(ImageDecoderMetadata, RLE4BMP) { CheckMetadata(RLE4BMPTestCase()); } +TEST_F(ImageDecoderMetadata, RLE8BMP) { CheckMetadata(RLE8BMPTestCase()); } -TEST(ImageMetadata, Corrupt) { CheckMetadata(CorruptTestCase()); } +TEST_F(ImageDecoderMetadata, Corrupt) { CheckMetadata(CorruptTestCase()); } -TEST(ImageMetadata, NoFrameDelayGIF) +TEST_F(ImageDecoderMetadata, NoFrameDelayGIF) { CheckMetadata(NoFrameDelayGIFTestCase()); } -TEST(ImageMetadata, NoFrameDelayGIFFullDecode) +TEST_F(ImageDecoderMetadata, NoFrameDelayGIFFullDecode) { ImageTestCase testCase = NoFrameDelayGIFTestCase(); diff --git a/image/test/gtest/TestSurfacePipeIntegration.cpp b/image/test/gtest/TestSurfacePipeIntegration.cpp index d7687a8a2af8..4cd429a74568 100644 --- a/image/test/gtest/TestSurfacePipeIntegration.cpp +++ b/image/test/gtest/TestSurfacePipeIntegration.cpp @@ -129,7 +129,18 @@ CheckPalettedSurfacePipeMethodResults(SurfacePipe* aPipe, EXPECT_TRUE(invalidRect.isNothing()); } -TEST(ImageSurfacePipeIntegration, SurfacePipe) +class ImageSurfacePipeIntegration : public ::testing::Test +{ + protected: + static void SetUpTestCase() + { + // Ensure that ImageLib services are initialized. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + EXPECT_TRUE(imgTools != nullptr); + } +}; + +TEST_F(ImageSurfacePipeIntegration, SurfacePipe) { // Test that SurfacePipe objects can be initialized and move constructed. SurfacePipe pipe = TestSurfacePipeFactory::SimpleSurfacePipe(); @@ -213,7 +224,7 @@ TEST(ImageSurfacePipeIntegration, SurfacePipe) currentFrame->Finish(); } -TEST(ImageSurfacePipeIntegration, PalettedSurfacePipe) +TEST_F(ImageSurfacePipeIntegration, PalettedSurfacePipe) { // Create a SurfacePipe containing a PalettedSurfaceSink. RefPtr decoder = CreateTrivialDecoder(); @@ -293,7 +304,7 @@ TEST(ImageSurfacePipeIntegration, PalettedSurfacePipe) currentFrame->Finish(); } -TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) +TEST_F(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) { RefPtr decoder = CreateTrivialDecoder(); ASSERT_TRUE(decoder != nullptr); @@ -311,7 +322,7 @@ TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels) SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixels) +TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixels) { // This test case uses a frame rect that extends beyond the borders of the // image to the bottom and to the right. It looks roughly like this (with the @@ -367,7 +378,7 @@ TEST(ImageSurfacePipeIntegration, RemoveFrameRectBottomRightDownscaleWritePixels SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels) +TEST_F(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels) { // This test case uses a frame rect that extends beyond the borders of the // image to the top and to the left. It looks roughly like this (with the @@ -401,7 +412,7 @@ TEST(ImageSurfacePipeIntegration, RemoveFrameRectTopLeftDownscaleWritePixels) SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) +TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) { RefPtr decoder = CreateTrivialDecoder(); ASSERT_TRUE(decoder != nullptr); @@ -425,7 +436,7 @@ TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels) SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels) +TEST_F(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels) { RefPtr decoder = CreateTrivialDecoder(); ASSERT_TRUE(decoder != nullptr); @@ -448,7 +459,7 @@ TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels SurfaceFormat::B8G8R8A8, false }); } -TEST(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFails) +TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFails) { RefPtr decoder = CreateTrivialDecoder(); ASSERT_TRUE(decoder != nullptr); @@ -465,7 +476,7 @@ TEST(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFai false }); } -TEST(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails) +TEST_F(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails) { RefPtr decoder = CreateTrivialDecoder(); ASSERT_TRUE(decoder != nullptr); @@ -481,3 +492,22 @@ TEST(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails) SurfaceFormat::B8G8R8A8, 8, false }); } + +TEST_F(ImageSurfacePipeIntegration, ConfiguringHugeDeinterlacingBufferFails) +{ + RefPtr decoder = CreateTrivialDecoder(); + ASSERT_TRUE(decoder != nullptr); + + // When DownscalingFilter is used, we may succeed in allocating an output + // surface for huge images, because we only need to store the scaled-down + // version of the image. However, regardless of downscaling, + // DeinterlacingFilter needs to allocate a buffer as large as the size of the + // input. This can cause OOMs on operating systems that allow overcommit. This + // test makes sure that we reject such allocations. + AssertConfiguringPipelineFails(decoder, + DeinterlacingConfig { /* mProgressiveDisplay = */ true}, + DownscalingConfig { IntSize(60000, 60000), + SurfaceFormat::B8G8R8A8 }, + SurfaceConfig { decoder, 0, IntSize(600, 600), + SurfaceFormat::B8G8R8A8, false }); +}