[vm/io] Range check Socket_SendMessage arguments

Closes https://github.com/dart-lang/sdk/pull/63365

GitOrigin-RevId: 344604dd1a17b73c6665026e7e75693fe0fa7ca7
Change-Id: I8f51d5735a56564f2181bcd1206c9cfdff80f077
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/502960
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
peeefour
2026-05-13 03:40:04 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 119d9d72b7
commit 1d80afe498
3 changed files with 49 additions and 3 deletions
+6 -1
View File
@@ -828,7 +828,12 @@ void FUNCTION_NAME(Socket_SendMessage)(Dart_NativeArguments args) {
Dart_Handle buffer_dart = Dart_GetNativeArgument(args, 1);
TypedDataScope data(buffer_dart);
ASSERT((offset + length) <= data.size_in_bytes());
const intptr_t end = offset + length;
if (!(0 <= offset && offset <= end && end <= data.size_in_bytes())) {
delete os_error;
Dart_SetReturnValue(args, Dart_NewApiError("Invalid range"));
return;
}
uint8_t* buffer_at_offset =
reinterpret_cast<uint8_t*>(data.data()) + offset;
bytes_written = SocketBase::SendMessage(
+2 -2
View File
@@ -1524,7 +1524,7 @@ base class _NativeSocket extends _NativeSocketNativeWrapper
_BufferAndStart bufferAndStart = _ensureFastAndSerializableByteData(
buffer,
offset,
bytes,
offset + bytes,
);
if (!const bool.fromEnvironment("dart.vm.product")) {
_SocketProfile.collectStatistic(
@@ -1568,7 +1568,7 @@ base class _NativeSocket extends _NativeSocketNativeWrapper
_BufferAndStart bufferAndStart = _ensureFastAndSerializableByteData(
buffer,
offset,
bytes,
offset + bytes,
);
if (!const bool.fromEnvironment("dart.vm.product")) {
_SocketProfile.collectStatistic(
@@ -0,0 +1,41 @@
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:expect/expect.dart';
Future<void> main() async {
// sendMessage with control messages is POSIX-only.
if (!(Platform.isLinux || Platform.isMacOS)) {
return;
}
final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
final got = Completer<List<int>>();
server.listen((sock) {
sock.close();
got.complete(sock.expand((v) => v).toList());
});
final client = await RawSocket.connect(
InternetAddress.loopbackIPv4,
server.port,
);
// `data` is a plain `List<int>` (not a `Uint8List`), forcing the helper
// to take its copy path.
final data = List<int>.generate(16, (i) => i);
client.sendMessage(const <SocketControlMessage>[], data, 5, 10);
client.close();
final received = await got.future.timeout(const Duration(seconds: 5));
await server.close();
Expect.equals(10, received.length);
Expect.listEquals(<int>[5, 6, 7, 8, 9, 10, 11, 12, 13, 14], received);
}