[vm] Fix Dart_PostCObject to not run finalizers when a message fails to post.

Bug: https://github.com/dart-lang/sdk/issues/40627
Change-Id: I4a6d49008d8cf73b2bcaca512d52ddcbe7b41c05
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135796
Reviewed-by: Chinmay Garde <chinmaygarde@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2020-02-14 17:50:42 +00:00 committed by commit-bot@chromium.org
parent da9dd59eb0
commit 467e82b668
4 changed files with 39 additions and 0 deletions

View file

@ -6430,6 +6430,30 @@ TEST_CASE(DartAPI_IllegalPost) {
EXPECT(!success);
}
static void UnreachableFinalizer(void* isolate_callback_data,
Dart_WeakPersistentHandle handle,
void* peer) {
UNREACHABLE();
}
TEST_CASE(DartAPI_PostCObject_DoesNotRunFinalizerOnFailure) {
char* my_str = strdup("Ownership of this memory remains with the caller");
Dart_CObject message;
message.type = Dart_CObject_kExternalTypedData;
message.value.as_external_typed_data.type = Dart_TypedData_kUint8;
message.value.as_external_typed_data.length = strlen(my_str);
message.value.as_external_typed_data.data =
reinterpret_cast<uint8_t*>(my_str);
message.value.as_external_typed_data.peer = my_str;
message.value.as_external_typed_data.callback = UnreachableFinalizer;
bool success = Dart_PostCObject(ILLEGAL_PORT, &message);
EXPECT(!success);
free(my_str); // Never a double-free.
}
VM_UNIT_TEST_CASE(DartAPI_NewNativePort) {
// Create a port with a bogus handler.
Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true);

View file

@ -70,6 +70,13 @@ class MessageFinalizableData {
}
}
void DropFinalizers() {
records_.Clear();
get_position_ = 0;
take_position_ = 0;
external_size_ = 0;
}
intptr_t external_size() const { return external_size_; }
private:

View file

@ -98,6 +98,12 @@ class Message {
bool RedirectToDeliveryFailurePort();
void DropFinalizers() {
if (finalizable_data_ != nullptr) {
finalizable_data_->DropFinalizers();
}
}
intptr_t Id() const;
static const char* PriorityAsString(Priority priority);

View file

@ -249,6 +249,8 @@ bool PortMap::PostMessage(std::unique_ptr<Message> message,
MutexLocker ml(mutex_);
intptr_t index = FindPort(message->dest_port());
if (index < 0) {
// Ownership of external data remains with the poster.
message->DropFinalizers();
return false;
}
ASSERT(index >= 0);