Skip to content

Commit d2f7039

Browse files
zichanggcommit-bot@chromium.org
authored andcommitted
[dart:io] Parse scoped IPv6 in constructor of InternetAddress
Bug: #41663 Change-Id: Ic7a140bc335e56550e39bb30390247db668c6101 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/147060 Commit-Queue: Zichang Guo <zichangguo@google.com> Reviewed-by: Jonas Termansen <sortie@google.com> Reviewed-by: Zach Anderson <zra@google.com>
1 parent c2d28d1 commit d2f7039

File tree

5 files changed

+76
-17
lines changed

5 files changed

+76
-17
lines changed

runtime/bin/io_natives.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ namespace bin {
8282
V(Filter_Process, 4) \
8383
V(Filter_Processed, 3) \
8484
V(InternetAddress_Parse, 1) \
85+
V(InternetAddress_ParseScopedLinkLocalAddress, 1) \
8586
V(InternetAddress_RawAddrToString, 1) \
8687
V(IOService_NewServicePort, 0) \
8788
V(Namespace_Create, 2) \

runtime/bin/socket_base.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,31 @@ void FUNCTION_NAME(InternetAddress_Parse)(Dart_NativeArguments args) {
243243
}
244244
}
245245

246+
void FUNCTION_NAME(InternetAddress_ParseScopedLinkLocalAddress)(
247+
Dart_NativeArguments args) {
248+
const char* address =
249+
DartUtils::GetStringValue(Dart_GetNativeArgument(args, 0));
250+
// This must be an IPv6 address.
251+
intptr_t type = 1;
252+
ASSERT(address != NULL);
253+
OSError* os_error = NULL;
254+
AddressList<SocketAddress>* addresses =
255+
SocketBase::LookupAddress(address, type, &os_error);
256+
if (addresses != NULL) {
257+
Dart_Handle list = Dart_NewList(addresses->count());
258+
for (intptr_t i = 0; i < addresses->count(); i++) {
259+
SocketAddress* addr = addresses->GetAt(i);
260+
Dart_ListSetAt(
261+
list, i, Dart_NewInteger(SocketAddress::GetAddrScope(addr->addr())));
262+
}
263+
delete addresses;
264+
Dart_SetReturnValue(args, list);
265+
} else {
266+
Dart_SetReturnValue(args, DartUtils::NewDartOSError(os_error));
267+
delete os_error;
268+
}
269+
}
270+
246271
void FUNCTION_NAME(InternetAddress_RawAddrToString)(Dart_NativeArguments args) {
247272
RawAddr addr;
248273
SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 0), &addr);

sdk/lib/_internal/vm/bin/socket_patch.dart

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,36 @@ class _InternetAddress implements InternetAddress {
226226
return _InternetAddress(
227227
InternetAddressType.unix, address, null, rawAddress);
228228
} else {
229-
var in_addr = _parse(address);
230-
if (in_addr == null) {
231-
throw ArgumentError("Invalid internet address $address");
229+
int index = address.indexOf('%');
230+
String originalAddress = address;
231+
String? scopeID;
232+
if (index > 0) {
233+
scopeID = address.substring(index, address.length);
234+
address = address.substring(0, index);
232235
}
233-
InternetAddressType type = in_addr.length == _IPv4AddrLength
236+
var inAddr = _parse(address);
237+
if (inAddr == null) {
238+
throw ArgumentError.value("Invalid internet address $address");
239+
}
240+
InternetAddressType type = inAddr.length == _IPv4AddrLength
234241
? InternetAddressType.IPv4
235242
: InternetAddressType.IPv6;
236-
return _InternetAddress(type, address, null, in_addr);
243+
if (scopeID != null && scopeID.length > 0) {
244+
if (type != InternetAddressType.IPv6) {
245+
throw ArgumentError.value("IPv4 addresses cannot have a scope id");
246+
}
247+
// This is an IPv6 address with scope id.
248+
var list = _parseScopedLinkLocalAddress(originalAddress);
249+
250+
if (list is! OSError && (list as List).isNotEmpty) {
251+
return _InternetAddress(InternetAddressType.IPv6, originalAddress,
252+
null, inAddr, list.first);
253+
} else {
254+
throw ArgumentError.value(
255+
"Invalid IPv6 address $address with scope ID");
256+
}
257+
}
258+
return _InternetAddress(type, originalAddress, null, inAddr, 0);
237259
}
238260
}
239261

@@ -262,12 +284,11 @@ class _InternetAddress implements InternetAddress {
262284

263285
static _InternetAddress? tryParse(String address) {
264286
checkNotNullable(address, "address");
265-
var addressBytes = _parse(address);
266-
if (addressBytes == null) return null;
267-
var type = addressBytes.length == _IPv4AddrLength
268-
? InternetAddressType.IPv4
269-
: InternetAddressType.IPv6;
270-
return _InternetAddress(type, address, null, addressBytes);
287+
try {
288+
return _InternetAddress.fromString(address);
289+
} catch (e) {
290+
return null;
291+
}
271292
}
272293

273294
factory _InternetAddress.fixed(int id) {
@@ -297,7 +318,8 @@ class _InternetAddress implements InternetAddress {
297318

298319
// Create a clone of this _InternetAddress replacing the host.
299320
_InternetAddress _cloneWithNewHost(String host) {
300-
return _InternetAddress(type, address, host, Uint8List.fromList(_in_addr));
321+
return _InternetAddress(
322+
type, address, host, Uint8List.fromList(_in_addr), _scope_id);
301323
}
302324

303325
bool operator ==(other) {
@@ -330,7 +352,8 @@ class _InternetAddress implements InternetAddress {
330352

331353
static String _rawAddrToString(Uint8List address)
332354
native "InternetAddress_RawAddrToString";
333-
355+
static List _parseScopedLinkLocalAddress(String address)
356+
native "InternetAddress_ParseScopedLinkLocalAddress";
334357
static Uint8List? _parse(String address) native "InternetAddress_Parse";
335358
}
336359

tests/standalone/io/http_linklocal_ipv6_test.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ void main() {
1616
// ip address show
1717
asyncStart();
1818
try {
19-
// Make sure the address here is the same as what it shows in "ip address show"
20-
var ipv6 = 'fe80:1::10%tap0';
19+
// Make sure the address here is the same as what it shows in
20+
// "ip address show"
21+
var ipv6 = 'fe80:1::1%tap0';
22+
23+
// Parses a Link-local address on Linux and Windows will throw an exception.
24+
InternetAddress(ipv6);
25+
2126
HttpServer.bind(ipv6, 0).then((server) {
2227
server.listen((request) {
2328
var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {

tests/standalone_2/io/http_linklocal_ipv6_test.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ void main() {
1616
// ip address show
1717
asyncStart();
1818
try {
19-
// Make sure the address here is the same as what it shows in "ip address show"
20-
var ipv6 = 'fe80:1::10%tap0';
19+
// Make sure the address here is the same as what it shows in
20+
// "ip address show"
21+
var ipv6 = 'fe80:1::1%tap0';
22+
23+
// Parses a Link-local address on Linux and Windows will throw an exception.
24+
InternetAddress(ipv6);
25+
2126
HttpServer.bind(ipv6, 0).then((server) {
2227
server.listen((request) {
2328
var timer = new Timer.periodic(const Duration(milliseconds: 0), (_) {

0 commit comments

Comments
 (0)