Bug 971695 - 1/2 - make ImageDataSerializer check data size - r=nical

This commit is contained in:
Benoit Jacob 2014-02-20 16:04:11 -05:00
parent 798ec9614e
commit 9b3a0b05a4
6 changed files with 79 additions and 28 deletions

View File

@ -48,20 +48,23 @@ struct SurfaceBufferInfo
} // anonymous namespace
static SurfaceBufferInfo*
GetBufferInfo(uint8_t* aBuffer)
GetBufferInfo(uint8_t* aData, size_t aDataSize)
{
return reinterpret_cast<SurfaceBufferInfo*>(aBuffer);
return aDataSize >= sizeof(SurfaceBufferInfo)
? reinterpret_cast<SurfaceBufferInfo*>(aData)
: nullptr;
}
void
ImageDataSerializer::InitializeBufferInfo(IntSize aSize,
SurfaceFormat aFormat)
{
SurfaceBufferInfo* info = GetBufferInfo(mData);
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
info->width = aSize.width;
info->height = aSize.height;
info->format = aFormat;
Validate();
}
static inline uint32_t
@ -71,7 +74,7 @@ ComputeStride(SurfaceFormat aFormat, uint32_t aWidth)
}
uint32_t
ImageDataSerializer::ComputeMinBufferSize(IntSize aSize,
ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
SurfaceFormat aFormat)
{
uint32_t bufsize = aSize.height * ComputeStride(aFormat, aSize.width);
@ -79,11 +82,20 @@ ImageDataSerializer::ComputeMinBufferSize(IntSize aSize,
+ GetAlignedStride<16>(bufsize);
}
bool
ImageDataSerializerBase::IsValid() const
void
ImageDataSerializerBase::Validate()
{
// XXX - We could use some sanity checks here.
return !!mData;
mIsValid = false;
if (!mData) {
return;
}
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
if (!info) {
return;
}
size_t requiredSize =
ComputeMinBufferSize(IntSize(info->width, info->height), info->format);
mIsValid = requiredSize <= mDataSize;
}
uint8_t*
@ -97,7 +109,7 @@ uint32_t
ImageDataSerializerBase::GetStride() const
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
return ComputeStride(GetFormat(), info->width);
}
@ -105,7 +117,7 @@ IntSize
ImageDataSerializerBase::GetSize() const
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
return IntSize(info->width, info->height);
}
@ -113,7 +125,7 @@ SurfaceFormat
ImageDataSerializerBase::GetFormat() const
{
MOZ_ASSERT(IsValid());
return GetBufferInfo(mData)->format;
return GetBufferInfo(mData, mDataSize)->format;
}
TemporaryRef<gfxImageSurface>

View File

@ -29,7 +29,7 @@ namespace layers {
class ImageDataSerializerBase
{
public:
bool IsValid() const;
bool IsValid() const { return mIsValid; }
uint8_t* GetData();
uint32_t GetStride() const;
@ -39,11 +39,22 @@ public:
TemporaryRef<gfxImageSurface> GetAsThebesSurface();
TemporaryRef<gfx::DrawTarget> GetAsDrawTarget();
static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
protected:
ImageDataSerializerBase(uint8_t* aData)
: mData(aData) {}
ImageDataSerializerBase(uint8_t* aData, size_t aDataSize)
: mData(aData)
, mDataSize(aDataSize)
, mIsValid(false)
{}
void Validate();
uint8_t* mData;
size_t mDataSize;
bool mIsValid;
};
/**
@ -56,11 +67,14 @@ protected:
class MOZ_STACK_CLASS ImageDataSerializer : public ImageDataSerializerBase
{
public:
ImageDataSerializer(uint8_t* aData) : ImageDataSerializerBase(aData) {}
ImageDataSerializer(uint8_t* aData, size_t aDataSize)
: ImageDataSerializerBase(aData, aDataSize)
{
// a serializer needs to be usable before correct buffer info has been written to it
mIsValid = !!mData;
}
void InitializeBufferInfo(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat);
};
/**
@ -70,7 +84,11 @@ public:
class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase
{
public:
ImageDataDeserializer(uint8_t* aData) : ImageDataSerializerBase(aData) {}
ImageDataDeserializer(uint8_t* aData, size_t aDataSize)
: ImageDataSerializerBase(aData, aDataSize)
{
Validate();
}
};
} // namespace layers

View File

@ -450,7 +450,7 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
MOZ_ASSERT(!IsImmutable());
MOZ_ASSERT(IsValid());
ImageDataSerializer serializer(GetBuffer());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (!serializer.IsValid()) {
return false;
}
@ -488,7 +488,7 @@ BufferTextureClient::GetAsSurface()
{
MOZ_ASSERT(IsValid());
ImageDataSerializer serializer(GetBuffer());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (!serializer.IsValid()) {
return nullptr;
}
@ -515,7 +515,7 @@ BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFla
memset(GetBuffer(), 0, bufSize);
}
ImageDataSerializer serializer(GetBuffer());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
serializer.InitializeBufferInfo(aSize, mFormat);
mSize = aSize;
return true;
@ -532,7 +532,7 @@ BufferTextureClient::GetAsDrawTarget()
return mDrawTarget;
}
ImageDataSerializer serializer(GetBuffer());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (!serializer.IsValid()) {
return nullptr;
}
@ -589,7 +589,7 @@ BufferTextureClient::Unlock()
// memory.
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
RefPtr<DataSourceSurface> surface = snapshot->GetDataSurface();
ImageDataSerializer serializer(GetBuffer());
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
if (!serializer.IsValid() || serializer.GetSize() != surface->GetSize()) {
NS_WARNING("Could not write the data back into the texture.");
mDrawTarget = nullptr;

View File

@ -22,6 +22,7 @@
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsPrintfCString.h" // for nsPrintfCString
#include "mozilla/layers/PTextureParent.h"
#include <limits>
struct nsIntPoint;
@ -557,9 +558,9 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
if (!mFirstSource) {
mFirstSource = mCompositor->CreateDataTextureSource();
}
ImageDataDeserializer deserializer(GetBuffer());
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
if (!deserializer.IsValid()) {
NS_WARNING("failed to open shmem surface");
NS_ERROR("Failed to deserialize image!");
return false;
}
@ -590,8 +591,9 @@ BufferTextureHost::GetAsSurface()
}
result = yuvDeserializer.ToDataSourceSurface();
} else {
ImageDataDeserializer deserializer(GetBuffer());
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
if (!deserializer.IsValid()) {
NS_ERROR("Failed to deserialize image!");
return nullptr;
}
result = deserializer.GetAsSurface();
@ -650,6 +652,11 @@ uint8_t* ShmemTextureHost::GetBuffer()
return mShmem ? mShmem->get<uint8_t>() : nullptr;
}
size_t ShmemTextureHost::GetBufferSize()
{
return mShmem ? mShmem->Size<uint8_t>() : 0;
}
MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
gfx::SurfaceFormat aFormat,
TextureFlags aFlags)
@ -688,6 +695,15 @@ uint8_t* MemoryTextureHost::GetBuffer()
return mBuffer;
}
size_t MemoryTextureHost::GetBufferSize()
{
// MemoryTextureHost just trusts that the buffer size is large enough to read
// anything we need to. That's because MemoryTextureHost has to trust the buffer
// pointer anyway, so the security model here is just that MemoryTexture's
// are restricted to same-process clients.
return std::numeric_limits<size_t>::max();
}
TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
: mAllocator(aAllocator)
{

View File

@ -444,6 +444,7 @@ public:
~BufferTextureHost();
virtual uint8_t* GetBuffer() = 0;
virtual size_t GetBufferSize() = 0;
virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
@ -506,6 +507,8 @@ public:
virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
virtual size_t GetBufferSize() MOZ_OVERRIDE;
virtual const char *Name() MOZ_OVERRIDE { return "ShmemTextureHost"; }
virtual void OnShutdown() MOZ_OVERRIDE;
@ -536,6 +539,8 @@ public:
virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
virtual size_t GetBufferSize() MOZ_OVERRIDE;
virtual const char *Name() MOZ_OVERRIDE { return "MemoryTextureHost"; }
protected:

View File

@ -216,7 +216,7 @@ SharedRGBImage::GetBuffer()
return nullptr;
}
ImageDataSerializer serializer(mTextureClient->GetBuffer());
ImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
return serializer.GetData();
}