[io/domain_sockets] Ensure OSError is released in case Dart_ThrowException reports an error.
Fixes https://github.com/dart-lang/sdk/issues/47428.
Also truncate buffer only if allocated buffer is larger than number of bytes received.
TEST=unix_socket_test on asan
Change-Id: I4d707d3bec48a33f900bca002f09f70e017597e4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/216261
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index ac9d95d..2333b43 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -658,6 +658,7 @@
int64_t buffer_num_bytes = 0;
DartUtils::GetInt64Value(ThrowIfError(Dart_GetNativeArgument(args, 1)),
&buffer_num_bytes);
+ int64_t buffer_num_bytes_allocated = buffer_num_bytes;
uint8_t* buffer = nullptr;
Dart_Handle data = IOBuffer::Allocate(buffer_num_bytes, &buffer);
if (Dart_IsNull(data)) {
@@ -665,16 +666,21 @@
}
ASSERT(buffer != nullptr);
- OSError os_error;
+ // Can't rely on RAII since Dart_ThrowException won't call destructors.
+ OSError* os_error = new OSError();
SocketControlMessage* control_messages;
const intptr_t messages_read = SocketBase::ReceiveMessage(
socket->fd(), buffer, &buffer_num_bytes, &control_messages,
- SocketBase::kAsync, &os_error);
+ SocketBase::kAsync, os_error);
if (messages_read < 0) {
ASSERT(messages_read == -1);
- Dart_ThrowException(DartUtils::NewDartOSError(&os_error));
+ Dart_Handle error = DartUtils::NewDartOSError(os_error);
+ delete os_error;
+ Dart_ThrowException(error);
}
- if (buffer_num_bytes > 0) {
+ delete os_error;
+ if (buffer_num_bytes > 0 && buffer_num_bytes != buffer_num_bytes_allocated) {
+ // If received fewer than allocated buffer size, truncate buffer.
uint8_t* new_buffer = nullptr;
Dart_Handle new_data = IOBuffer::Allocate(buffer_num_bytes, &new_buffer);
if (Dart_IsNull(new_data)) {
@@ -789,7 +795,8 @@
SocketControlMessage(level, type, copied_data, data.size_in_bytes());
}
- OSError os_error;
+ // Can't rely on RAII since Dart_ThrowException won't call destructors.
+ OSError* os_error = new OSError();
intptr_t bytes_written;
{
Dart_Handle buffer_dart = Dart_GetNativeArgument(args, 1);
@@ -800,12 +807,15 @@
reinterpret_cast<uint8_t*>(data.data()) + offset;
bytes_written = SocketBase::SendMessage(
socket->fd(), buffer_at_offset, length, control_messages,
- num_control_messages, SocketBase::kAsync, &os_error);
+ num_control_messages, SocketBase::kAsync, os_error);
}
if (bytes_written < 0) {
- Dart_ThrowException(DartUtils::NewDartOSError(&os_error));
+ Dart_Handle error = DartUtils::NewDartOSError(os_error);
+ delete os_error;
+ Dart_ThrowException(error);
}
+ delete os_error;
Dart_SetIntegerReturnValue(args, bytes_written);
}