Do not crash when out of memory at ImageData::create().

The old implementation was "allocate or die".  It's not good for
ImageData, which may try to allocate a huge memory block.  This CL
makes ImageData gracefully returns nullptr optionally raising an
exception in case of out of memory.

BUG=528898

Review URL: https://codereview.chromium.org/1328343002

git-svn-id: svn://svn.chromium.org/blink/trunk@201982 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 0bad3920
......@@ -52,6 +52,12 @@ public:
return adoptRef(new ThisType(bufferView.release(), buffer.release()));
}
static PassRefPtr<ThisType> createOrNull(unsigned length)
{
RefPtr<WTF::ArrayBuffer> buffer = WTF::ArrayBuffer::createOrNull(length, 1);
return buffer ? create(buffer.release(), 0, length) : nullptr;
}
const WTFTypedArray* view() const { return static_cast<const WTFTypedArray*>(DOMArrayBufferView::view()); }
WTFTypedArray* view() { return static_cast<WTFTypedArray*>(DOMArrayBufferView::view()); }
......
......@@ -41,10 +41,15 @@ ImageData* ImageData::create(const IntSize& size)
Checked<int, RecordOverflow> dataSize = 4;
dataSize *= size.width();
dataSize *= size.height();
if (dataSize.hasOverflowed())
if (dataSize.hasOverflowed() || dataSize.unsafeGet() < 0)
return nullptr;
RefPtr<DOMUint8ClampedArray> byteArray =
DOMUint8ClampedArray::createOrNull(dataSize.unsafeGet());
if (!byteArray)
return nullptr;
return new ImageData(size);
return new ImageData(size, byteArray.release());
}
ImageData* ImageData::create(const IntSize& size, PassRefPtr<DOMUint8ClampedArray> byteArray)
......@@ -72,12 +77,21 @@ ImageData* ImageData::create(unsigned width, unsigned height, ExceptionState& ex
Checked<unsigned, RecordOverflow> dataSize = 4;
dataSize *= width;
dataSize *= height;
if (dataSize.hasOverflowed()) {
if (dataSize.hasOverflowed()
|| static_cast<int>(width) < 0
|| static_cast<int>(height) < 0) {
exceptionState.throwDOMException(IndexSizeError, "The requested image size exceeds the supported range.");
return nullptr;
}
return new ImageData(IntSize(width, height));
RefPtr<DOMUint8ClampedArray> byteArray =
DOMUint8ClampedArray::createOrNull(dataSize.unsafeGet());
if (!byteArray) {
exceptionState.throwDOMException(V8GeneralError, "Out of memory at ImageData creation");
return nullptr;
}
return new ImageData(IntSize(width, height), byteArray.release());
}
bool ImageData::validateConstructorArguments(DOMUint8ClampedArray* data, unsigned width, unsigned& lengthInPixels, ExceptionState& exceptionState)
......@@ -147,12 +161,6 @@ v8::Local<v8::Object> ImageData::associateWithWrapper(v8::Isolate* isolate, cons
return wrapper;
}
ImageData::ImageData(const IntSize& size)
: m_size(size)
, m_data(DOMUint8ClampedArray::create(size.width() * size.height() * 4))
{
}
ImageData::ImageData(const IntSize& size, PassRefPtr<DOMUint8ClampedArray> byteArray)
: m_size(size)
, m_data(byteArray)
......
......@@ -62,7 +62,6 @@ public:
v8::Local<v8::Object> associateWithWrapper(v8::Isolate*, const WrapperTypeInfo*, v8::Local<v8::Object> wrapper) override WARN_UNUSED_RETURN;
private:
explicit ImageData(const IntSize&);
ImageData(const IntSize&, PassRefPtr<DOMUint8ClampedArray>);
static bool validateConstructorArguments(DOMUint8ClampedArray*, unsigned width, unsigned&, ExceptionState&);
......
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