Fix potential use-after-free of V8TrackArrayBuffer (fixes issue #3074)

This commit is contained in:
Marshall Greenblatt 2021-03-22 13:52:01 -04:00
parent 69a8839ce9
commit 64a1612b70

View File

@ -322,7 +322,8 @@ class V8TrackArrayBuffer : public CefTrackNode {
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback)
: isolate_(isolate), : isolate_(isolate),
buffer_(buffer), buffer_(buffer),
release_callback_(release_callback) { release_callback_(release_callback),
weak_ptr_factory_(this) {
DCHECK(isolate_); DCHECK(isolate_);
isolate_->AdjustAmountOfExternalAllocatedMemory( isolate_->AdjustAmountOfExternalAllocatedMemory(
static_cast<int>(sizeof(V8TrackArrayBuffer))); static_cast<int>(sizeof(V8TrackArrayBuffer)));
@ -365,10 +366,16 @@ class V8TrackArrayBuffer : public CefTrackNode {
return nullptr; return nullptr;
} }
base::WeakPtr<V8TrackArrayBuffer> GetWeakPtr() const {
return weak_ptr_factory_.GetWeakPtr();
}
private: private:
v8::Isolate* isolate_; v8::Isolate* isolate_;
void* buffer_; void* buffer_;
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_; CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_;
base::WeakPtrFactory<V8TrackArrayBuffer> weak_ptr_factory_;
}; };
// Object wrapped in a v8::External and passed as the Data argument to // Object wrapped in a v8::External and passed as the Data argument to
@ -1416,15 +1423,24 @@ CefRefPtr<CefV8Value> CefV8Value::CreateArrayBuffer(
V8TrackArrayBuffer* tracker = V8TrackArrayBuffer* tracker =
new V8TrackArrayBuffer(isolate, buffer, release_callback); new V8TrackArrayBuffer(isolate, buffer, release_callback);
struct WeakPtrWrapper {
WeakPtrWrapper(V8TrackArrayBuffer* tracker) {
weak_ptr_ = tracker->GetWeakPtr();
}
base::WeakPtr<V8TrackArrayBuffer> weak_ptr_;
};
auto deleter = [](void* data, size_t length, void* deleter_data) { auto deleter = [](void* data, size_t length, void* deleter_data) {
auto* tracker = reinterpret_cast<V8TrackArrayBuffer*>(deleter_data); auto* wrapper = reinterpret_cast<WeakPtrWrapper*>(deleter_data);
if (tracker) { if (wrapper) {
tracker->ReleaseBuffer(); if (wrapper->weak_ptr_)
wrapper->weak_ptr_->ReleaseBuffer();
delete wrapper;
} }
}; };
std::unique_ptr<v8::BackingStore> backing = std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore(
v8::ArrayBuffer::NewBackingStore(buffer, length, deleter, tracker); buffer, length, deleter, new WeakPtrWrapper(tracker));
v8::Local<v8::ArrayBuffer> ab = v8::Local<v8::ArrayBuffer> ab =
v8::ArrayBuffer::New(isolate, std::move(backing)); v8::ArrayBuffer::New(isolate, std::move(backing));