Bug 1315554 - Part 1. Enforce the parent decoder size (ICO) for child decoders (BMP, PNG). r=tnikkel

This commit is contained in:
Andrew Osmond 2017-07-22 00:14:58 -04:00
parent ef2b77779d
commit 1e83b97079
6 changed files with 42 additions and 1 deletions

View File

@ -405,6 +405,14 @@ Decoder::PostSize(int32_t aWidth,
// Set our intrinsic size.
mImageMetadata.SetSize(aWidth, aHeight, aOrientation);
// Verify it is the expected size, if given. Note that this is only used by
// the ICO decoder for embedded image types, so only its subdecoders are
// required to handle failures in PostSize.
if (!IsExpectedSize()) {
PostError();
return;
}
// Set our output size if it's not already set.
if (!mOutputSize) {
mOutputSize = Some(IntSize(aWidth, aHeight));

View File

@ -215,6 +215,23 @@ public:
*/
Maybe<gfx::IntSize> ExplicitOutputSize() const;
/**
* Sets the expected image size of this decoder. Decoding will fail if this
* does not match.
*/
void SetExpectedSize(const gfx::IntSize& aSize)
{
mExpectedSize.emplace(aSize);
}
/**
* Is the image size what was expected, if specified?
*/
bool IsExpectedSize() const
{
return mExpectedSize.isNothing() || *mExpectedSize == Size();
}
/**
* Set an iterator to the SourceBuffer which will feed data to this decoder.
* This must always be called before calling Init(). (And only before Init().)
@ -527,6 +544,7 @@ private:
ImageMetadata mImageMetadata;
gfx::IntRect mInvalidRect; // Tracks an invalidation region in the current frame.
Maybe<gfx::IntSize> mOutputSize; // The size of our output surface.
Maybe<gfx::IntSize> mExpectedSize; // The expected size of the image.
Progress mProgress;
uint32_t mFrameCount; // Number of frames, including anything in-progress

View File

@ -236,6 +236,7 @@ DecoderFactory::CreateMetadataDecoder(DecoderType aType,
DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
NotNull<SourceBuffer*> aSourceBuffer,
NotNull<nsICODecoder*> aICODecoder,
const Maybe<IntSize>& aExpectedSize,
const Maybe<uint32_t>& aDataOffset
/* = Nothing() */)
{
@ -264,6 +265,9 @@ DecoderFactory::CreateDecoderForICOResource(DecoderType aType,
decoder->SetMetadataDecode(aICODecoder->IsMetadataDecode());
decoder->SetIterator(aSourceBuffer->Iterator());
decoder->SetOutputSize(aICODecoder->OutputSize());
if (aExpectedSize) {
decoder->SetExpectedSize(*aExpectedSize);
}
decoder->SetDecoderFlags(aICODecoder->GetDecoderFlags());
decoder->SetSurfaceFlags(aICODecoder->GetSurfaceFlags());
decoder->SetFinalizeFrames(false);

View File

@ -126,6 +126,7 @@ public:
* resource decoder, so the two decoders will have the
* same decoder flags, surface flags, target size, and
* other parameters.
* @param aExpectedSize The expected size of the resource from the ICO header.
* @param aDataOffset If @aType is BMP, specifies the offset at which data
* begins in the BMP resource. Must be Some() if and only
* if @aType is BMP.
@ -134,6 +135,7 @@ public:
CreateDecoderForICOResource(DecoderType aType,
NotNull<SourceBuffer*> aSourceBuffer,
NotNull<nsICODecoder*> aICODecoder,
const Maybe<gfx::IntSize>& aExpectedSize,
const Maybe<uint32_t>& aDataOffset = Nothing());
/**

View File

@ -650,6 +650,9 @@ nsBMPDecoder::ReadBitfields(const char* aData, size_t aLength)
// Post our size to the superclass.
PostSize(mH.mWidth, AbsoluteHeight());
if (HasError()) {
return Transition::TerminateFailure();
}
// We've now read all the headers. If we're doing a metadata decode, we're
// done.

View File

@ -281,6 +281,10 @@ nsICODecoder::ReadDirEntry(const char* aData)
// is necessary for downscale-during-decode to work since we won't even
// attempt to *upscale* while decoding.
PostSize(mBiggestResourceSize.width, mBiggestResourceSize.height);
if (HasError()) {
return Transition::TerminateFailure();
}
if (IsMetadataDecode()) {
return Transition::TerminateSuccess();
}
@ -316,7 +320,8 @@ nsICODecoder::SniffResource(const char* aData)
mContainedDecoder =
DecoderFactory::CreateDecoderForICOResource(DecoderType::PNG,
WrapNotNull(mContainedSourceBuffer),
WrapNotNull(this));
WrapNotNull(this),
Some(GetRealSize()));
if (!WriteToContainedDecoder(aData, PNGSIGNATURESIZE)) {
return Transition::TerminateFailure();
@ -395,6 +400,7 @@ nsICODecoder::ReadBIH(const char* aData)
DecoderFactory::CreateDecoderForICOResource(DecoderType::BMP,
WrapNotNull(mContainedSourceBuffer),
WrapNotNull(this),
Some(GetRealSize()),
Some(dataOffset));
RefPtr<nsBMPDecoder> bmpDecoder =
static_cast<nsBMPDecoder*>(mContainedDecoder.get());