Skip to content

Commit

Permalink
Merge branch '4-2-x' into miniak/liftoff-correctly-unuse-labels-4-2-x
Browse files Browse the repository at this point in the history
  • Loading branch information
miniak committed Jun 4, 2019
2 parents 5745ca0 + ee6c91d commit 4585149
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 10 deletions.
2 changes: 1 addition & 1 deletion VERSION
@@ -1 +1 @@
4.2.3
4.2.4
4 changes: 2 additions & 2 deletions atom/browser/resources/mac/Info.plist
Expand Up @@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>electron.icns</string>
<key>CFBundleVersion</key>
<string>4.2.3</string>
<string>4.2.4</string>
<key>CFBundleShortVersionString</key>
<string>4.2.3</string>
<string>4.2.4</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
Expand Down
8 changes: 4 additions & 4 deletions atom/browser/resources/win/atom.rc
Expand Up @@ -50,8 +50,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 4,2,3,0
PRODUCTVERSION 4,2,3,0
FILEVERSION 4,2,4,0
PRODUCTVERSION 4,2,4,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "4.2.3"
VALUE "FileVersion", "4.2.4"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "4.2.3"
VALUE "ProductVersion", "4.2.4"
VALUE "SquirrelAwareVersion", "1"
END
END
Expand Down
2 changes: 1 addition & 1 deletion atom/common/atom_version.h
Expand Up @@ -7,7 +7,7 @@

#define ATOM_MAJOR_VERSION 4
#define ATOM_MINOR_VERSION 2
#define ATOM_PATCH_VERSION 3
#define ATOM_PATCH_VERSION 4
// clang-format off
// #define ATOM_PRE_RELEASE_VERSION
// clang-format on
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "4.2.3",
"version": "4.2.4",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions patches/common/chromium/.patches
Expand Up @@ -105,3 +105,4 @@ restore_live_region_changed_events_for_processing_by_jaws_focus_mode.patch
enable_quic_proxies_for_https_urls.patch
fix_svg_crash_for_v0_distribution_into_foreignobject.patch
filesystem_harden_against_overflows_of_operationid_a_bit_better.patch
fix_uap_in_imagebitmaploader_filereaderloader.patch
@@ -0,0 +1,134 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Marijn Kruisselbrink <mek@chromium.org>
Date: Thu, 13 Dec 2018 17:09:55 +0000
Subject: Fix UAP in ImageBitmapLoader/FileReaderLoader

FileReaderLoader stores its client as a raw pointer, so in cases like
ImageBitmapLoader where the FileReaderLoaderClient really is garbage
collected we have to make sure to destroy the FileReaderLoader when
the ExecutionContext that owns it is destroyed.

Bug: 913970
Change-Id: I40b02115367cf7bf5bbbbb8e9b57874d2510f861
Reviewed-on: https://chromium-review.googlesource.com/c/1374511
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#616342}

diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
index 076b9beeaa6675c5e858a1c7f5a321ab57c606fb..40898b704891c3723574d3afa4aebf72f5cdce5c 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc
@@ -238,27 +238,31 @@ void ImageBitmapFactories::DidFinishLoading(ImageBitmapLoader* loader) {
pending_loaders_.erase(loader);
}

+void ImageBitmapFactories::Trace(blink::Visitor* visitor) {
+ visitor->Trace(pending_loaders_);
+ Supplement<LocalDOMWindow>::Trace(visitor);
+ Supplement<WorkerGlobalScope>::Trace(visitor);
+}
+
ImageBitmapFactories::ImageBitmapLoader::ImageBitmapLoader(
ImageBitmapFactories& factory,
base::Optional<IntRect> crop_rect,
ScriptState* script_state,
const ImageBitmapOptions& options)
- : loader_(
+ : ContextLifecycleObserver(ExecutionContext::From(script_state)),
+ loader_(
FileReaderLoader::Create(FileReaderLoader::kReadAsArrayBuffer, this)),
factory_(&factory),
resolver_(ScriptPromiseResolver::Create(script_state)),
crop_rect_(crop_rect),
options_(options) {}

-void ImageBitmapFactories::ImageBitmapLoader::LoadBlobAsync(
- Blob* blob) {
+void ImageBitmapFactories::ImageBitmapLoader::LoadBlobAsync(Blob* blob) {
loader_->Start(blob->GetBlobDataHandle());
}

-void ImageBitmapFactories::Trace(blink::Visitor* visitor) {
- visitor->Trace(pending_loaders_);
- Supplement<LocalDOMWindow>::Trace(visitor);
- Supplement<WorkerGlobalScope>::Trace(visitor);
+ImageBitmapFactories::ImageBitmapLoader::~ImageBitmapLoader() {
+ DCHECK(!loader_);
}

void ImageBitmapFactories::ImageBitmapLoader::RejectPromise(
@@ -277,11 +281,20 @@ void ImageBitmapFactories::ImageBitmapLoader::RejectPromise(
default:
NOTREACHED();
}
+ loader_.reset();
factory_->DidFinishLoading(this);
}

+void ImageBitmapFactories::ImageBitmapLoader::ContextDestroyed(
+ ExecutionContext*) {
+ if (loader_)
+ factory_->DidFinishLoading(this);
+ loader_.reset();
+}
+
void ImageBitmapFactories::ImageBitmapLoader::DidFinishLoading() {
DOMArrayBuffer* array_buffer = loader_->ArrayBufferResult();
+ loader_.reset();
if (!array_buffer) {
RejectPromise(kAllocationFailureImageBitmapRejectionReason);
return;
@@ -359,6 +372,7 @@ void ImageBitmapFactories::ImageBitmapLoader::ResolvePromiseOnOriginalThread(
}

void ImageBitmapFactories::ImageBitmapLoader::Trace(blink::Visitor* visitor) {
+ ContextLifecycleObserver::Trace(visitor);
visitor->Trace(factory_);
visitor->Trace(resolver_);
}
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
index 25bdf1ffd1e85a05ab4ee46aaa81c61294fd7d1a..726012a20f7250ea1166ec03875ebaa10f352a49 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/bindings/core/v8/image_bitmap_source.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -103,7 +104,10 @@ class ImageBitmapFactories final
private:
class ImageBitmapLoader final
: public GarbageCollectedFinalized<ImageBitmapLoader>,
+ public ContextLifecycleObserver,
public FileReaderLoaderClient {
+ USING_GARBAGE_COLLECTED_MIXIN(ImageBitmapLoader);
+
public:
static ImageBitmapLoader* Create(ImageBitmapFactories& factory,
base::Optional<IntRect> crop_rect,
@@ -115,9 +119,9 @@ class ImageBitmapFactories final
void LoadBlobAsync(Blob*);
ScriptPromise Promise() { return resolver_->Promise(); }

- void Trace(blink::Visitor*);
+ void Trace(blink::Visitor*) override;

- ~ImageBitmapLoader() override = default;
+ ~ImageBitmapLoader() override;

private:
ImageBitmapLoader(ImageBitmapFactories&,
@@ -140,6 +144,9 @@ class ImageBitmapFactories final
const String& color_space_conversion_option);
void ResolvePromiseOnOriginalThread(sk_sp<SkImage>);

+ // ContextLifecycleObserver
+ void ContextDestroyed(ExecutionContext*) override;
+
// FileReaderLoaderClient
void DidStartLoading() override {}
void DidReceiveData() override {}
1 change: 1 addition & 0 deletions patches/common/v8/.patches
Expand Up @@ -23,4 +23,5 @@ do_not_export_private_v8_symbols_on_windows.patch
turbofan_fix_wrong_typing_of_speculativesafeintegersubtract.patch
turbofan_restrict_redundancy_elimination_from_widening_types.patch
parser_literalbuffer_expandbuffer_always_grows.patch
valueserializer_report_if_buffer_expansion_fails_during.patch
liftoff-correctly-unuse-labels.patch
@@ -0,0 +1,164 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jeremy Roman <jbroman@chromium.org>
Date: Thu, 13 Dec 2018 18:43:00 -0500
Subject: ValueSerializer: Report if buffer expansion fails during
WriteHostObject.

Also fail early if we detect that we've previously run out of memory and thus
corrupted the buffer.

Add a unit test for this kind of case.

Bug: chromium:914731
Change-Id: Iaaf3927209bffeab6fe8ba462d9dd9dad8cbbe2f
Reviewed-on: https://chromium-review.googlesource.com/c/1377449
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58248}

diff --git a/src/value-serializer.cc b/src/value-serializer.cc
index 4c9c9a9aa2d9ce6017bb02448fa474478c9f6308..8c85bd9f5466612937a71f8bfdcb82120f7fb9c7 100644
--- a/src/value-serializer.cc
+++ b/src/value-serializer.cc
@@ -344,7 +344,11 @@ void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
}

Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
- out_of_memory_ = false;
+ // There is no sense in trying to proceed if we've previously run out of
+ // memory. Bail immediately, as this likely implies that some write has
+ // previously failed and so the buffer is corrupt.
+ if (V8_UNLIKELY(out_of_memory_)) return ThrowIfOutOfMemory();
+
if (object->IsSmi()) {
WriteSmi(Smi::cast(*object));
return ThrowIfOutOfMemory();
@@ -930,8 +934,10 @@ Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
Maybe<bool> result =
delegate_->WriteHostObject(v8_isolate, Utils::ToLocal(object));
RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
+ USE(result);
DCHECK(!result.IsNothing());
- return result;
+ DCHECK(result.ToChecked());
+ return ThrowIfOutOfMemory();
}

Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
diff --git a/test/unittests/value-serializer-unittest.cc b/test/unittests/value-serializer-unittest.cc
index 92603b588ad13480460a166b556be18e57fc8ad6..bc738c84fc8b15bdfcdb0cc995f8002362292a4c 100644
--- a/test/unittests/value-serializer-unittest.cc
+++ b/test/unittests/value-serializer-unittest.cc
@@ -119,7 +119,10 @@ class ValueSerializerTest : public TestWithIsolate {
}
std::pair<uint8_t*, size_t> buffer = serializer.Release();
std::vector<uint8_t> result(buffer.first, buffer.first + buffer.second);
- free(buffer.first);
+ if (auto* delegate = GetSerializerDelegate())
+ delegate->FreeBufferMemory(buffer.first);
+ else
+ free(buffer.first);
return Just(std::move(result));
}

@@ -138,6 +141,10 @@ class ValueSerializerTest : public TestWithIsolate {
return buffer;
}

+ std::vector<uint8_t> EncodeTest(const char* source) {
+ return EncodeTest(EvaluateScriptForInput(source));
+ }
+
v8::Local<v8::Message> InvalidEncodeTest(Local<Value> input_value) {
Context::Scope scope(serialization_context());
TryCatch try_catch(isolate());
@@ -2698,5 +2705,89 @@ TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidDataLength) {
InvalidDecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x00, 0x7F});
}

+class ValueSerializerTestWithLimitedMemory : public ValueSerializerTest {
+ protected:
+// GMock doesn't use the "override" keyword.
+#if __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winconsistent-missing-override"
+#endif
+
+ class SerializerDelegate : public ValueSerializer::Delegate {
+ public:
+ explicit SerializerDelegate(ValueSerializerTestWithLimitedMemory* test)
+ : test_(test) {}
+
+ ~SerializerDelegate() { EXPECT_EQ(nullptr, last_buffer_); }
+
+ void SetMemoryLimit(size_t limit) { memory_limit_ = limit; }
+
+ void* ReallocateBufferMemory(void* old_buffer, size_t size,
+ size_t* actual_size) override {
+ EXPECT_EQ(old_buffer, last_buffer_);
+ if (size > memory_limit_) return nullptr;
+ *actual_size = size;
+ last_buffer_ = realloc(old_buffer, size);
+ return last_buffer_;
+ }
+
+ void FreeBufferMemory(void* buffer) override {
+ EXPECT_EQ(buffer, last_buffer_);
+ last_buffer_ = nullptr;
+ free(buffer);
+ }
+
+ void ThrowDataCloneError(Local<String> message) override {
+ test_->isolate()->ThrowException(Exception::Error(message));
+ }
+
+ MOCK_METHOD2(WriteHostObject,
+ Maybe<bool>(Isolate* isolate, Local<Object> object));
+
+ private:
+ ValueSerializerTestWithLimitedMemory* test_;
+ void* last_buffer_ = nullptr;
+ size_t memory_limit_ = 0;
+ };
+
+#if __clang__
+#pragma clang diagnostic pop
+#endif
+
+ ValueSerializer::Delegate* GetSerializerDelegate() override {
+ return &serializer_delegate_;
+ }
+
+ void BeforeEncode(ValueSerializer* serializer) override {
+ serializer_ = serializer;
+ }
+
+ SerializerDelegate serializer_delegate_{this};
+ ValueSerializer* serializer_ = nullptr;
+};
+
+TEST_F(ValueSerializerTestWithLimitedMemory, FailIfNoMemoryInWriteHostObject) {
+ EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
+ .WillRepeatedly(Invoke([this](Isolate*, Local<Object>) {
+ static const char kDummyData[1024] = {};
+ serializer_->WriteRawBytes(&kDummyData, sizeof(kDummyData));
+ return Just(true);
+ }));
+
+ // If there is enough memory, things work.
+ serializer_delegate_.SetMemoryLimit(2048);
+ EncodeTest("new ExampleHostObject()");
+
+ // If not, we get a graceful failure, rather than silent misbehavior.
+ serializer_delegate_.SetMemoryLimit(1024);
+ InvalidEncodeTest("new ExampleHostObject()");
+
+ // And we definitely don't continue to serialize other things.
+ serializer_delegate_.SetMemoryLimit(1024);
+ EvaluateScriptForInput("gotA = false");
+ InvalidEncodeTest("[new ExampleHostObject, {get a() { gotA = true; }}]");
+ EXPECT_TRUE(EvaluateScriptForInput("gotA")->IsFalse());
+}
+
} // namespace
} // namespace v8

0 comments on commit 4585149

Please sign in to comment.