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: ...@@ -52,6 +52,12 @@ public:
return adoptRef(new ThisType(bufferView.release(), buffer.release())); 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()); } const WTFTypedArray* view() const { return static_cast<const WTFTypedArray*>(DOMArrayBufferView::view()); }
WTFTypedArray* view() { return static_cast<WTFTypedArray*>(DOMArrayBufferView::view()); } WTFTypedArray* view() { return static_cast<WTFTypedArray*>(DOMArrayBufferView::view()); }
......
...@@ -41,10 +41,15 @@ ImageData* ImageData::create(const IntSize& size) ...@@ -41,10 +41,15 @@ ImageData* ImageData::create(const IntSize& size)
Checked<int, RecordOverflow> dataSize = 4; Checked<int, RecordOverflow> dataSize = 4;
dataSize *= size.width(); dataSize *= size.width();
dataSize *= size.height(); 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 nullptr;
return new ImageData(size); return new ImageData(size, byteArray.release());
} }
ImageData* ImageData::create(const IntSize& size, PassRefPtr<DOMUint8ClampedArray> byteArray) ImageData* ImageData::create(const IntSize& size, PassRefPtr<DOMUint8ClampedArray> byteArray)
...@@ -72,12 +77,21 @@ ImageData* ImageData::create(unsigned width, unsigned height, ExceptionState& ex ...@@ -72,12 +77,21 @@ ImageData* ImageData::create(unsigned width, unsigned height, ExceptionState& ex
Checked<unsigned, RecordOverflow> dataSize = 4; Checked<unsigned, RecordOverflow> dataSize = 4;
dataSize *= width; dataSize *= width;
dataSize *= height; 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."); exceptionState.throwDOMException(IndexSizeError, "The requested image size exceeds the supported range.");
return nullptr; 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) 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 ...@@ -147,12 +161,6 @@ v8::Local<v8::Object> ImageData::associateWithWrapper(v8::Isolate* isolate, cons
return wrapper; 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) ImageData::ImageData(const IntSize& size, PassRefPtr<DOMUint8ClampedArray> byteArray)
: m_size(size) : m_size(size)
, m_data(byteArray) , m_data(byteArray)
......
...@@ -62,7 +62,6 @@ public: ...@@ -62,7 +62,6 @@ public:
v8::Local<v8::Object> associateWithWrapper(v8::Isolate*, const WrapperTypeInfo*, v8::Local<v8::Object> wrapper) override WARN_UNUSED_RETURN; v8::Local<v8::Object> associateWithWrapper(v8::Isolate*, const WrapperTypeInfo*, v8::Local<v8::Object> wrapper) override WARN_UNUSED_RETURN;
private: private:
explicit ImageData(const IntSize&);
ImageData(const IntSize&, PassRefPtr<DOMUint8ClampedArray>); ImageData(const IntSize&, PassRefPtr<DOMUint8ClampedArray>);
static bool validateConstructorArguments(DOMUint8ClampedArray*, unsigned width, unsigned&, ExceptionState&); 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