Sanitize host before calling pm (#49591)
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart index 644bbb0..4e8e6f1 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_device.dart
@@ -27,6 +27,7 @@ import 'fuchsia_build.dart'; import 'fuchsia_pm.dart'; import 'fuchsia_sdk.dart'; +import 'fuchsia_utils.dart'; import 'fuchsia_workflow.dart'; import 'tiles_ctl.dart'; @@ -513,12 +514,7 @@ void clearLogs() {} bool get ipv6 { - try { - Uri.parseIPv6Address(id); - return true; - } on FormatException { - return false; - } + return isIPv6Address(id); } /// List the ports currently running a dart observatory.
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart index 9400470..d8ca646 100644 --- a/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_pm.dart
@@ -10,6 +10,7 @@ import '../globals.dart' as globals; import 'fuchsia_sdk.dart'; +import 'fuchsia_utils.dart'; /// This is a basic wrapper class for the Fuchsia SDK's `pm` tool. class FuchsiaPM { @@ -109,6 +110,9 @@ if (fuchsiaArtifacts.pm == null) { throwToolExit('Fuchsia pm tool not found'); } + if (isIPv6Address(host.split('%').first)) { + host = '[${host.replaceAll('%', '%25')}]'; + } final List<String> command = <String>[ fuchsiaArtifacts.pm.path, 'serve',
diff --git a/packages/flutter_tools/lib/src/fuchsia/fuchsia_utils.dart b/packages/flutter_tools/lib/src/fuchsia/fuchsia_utils.dart new file mode 100644 index 0000000..af25998 --- /dev/null +++ b/packages/flutter_tools/lib/src/fuchsia/fuchsia_utils.dart
@@ -0,0 +1,13 @@ +// Copyright 2014 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Returns [true] if [address] is an IPv6 address. +bool isIPv6Address(String address) { + try { + Uri.parseIPv6Address(address); + return true; + } on FormatException { + return false; + } +}
diff --git a/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart new file mode 100644 index 0000000..a4d3d8d --- /dev/null +++ b/packages/flutter_tools/test/general.shard/fuchsia/fuchsia_pm_test.dart
@@ -0,0 +1,80 @@ +// Copyright 2014 The Flutter Authors. 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 'package:flutter_tools/src/base/context.dart'; +import 'package:flutter_tools/src/base/file_system.dart'; +import 'package:flutter_tools/src/base/io.dart'; +import 'package:flutter_tools/src/base/process.dart'; +import 'package:flutter_tools/src/fuchsia/fuchsia_pm.dart'; +import 'package:flutter_tools/src/fuchsia/fuchsia_sdk.dart'; +import 'package:mockito/mockito.dart'; + +import '../../src/common.dart'; +import '../../src/context.dart'; +import '../../src/mocks.dart'; + +void main() { + group('FuchsiaPM', () { + MockFile pm; + MockProcessUtils mockProcessUtils; + MockFuchsiaArtifacts mockFuchsiaArtifacts; + + setUp(() { + pm = MockFile(); + when(pm.path).thenReturn('pm'); + + mockFuchsiaArtifacts = MockFuchsiaArtifacts(); + when(mockFuchsiaArtifacts.pm).thenReturn(pm); + + mockProcessUtils = MockProcessUtils(); + }); + + testUsingContext('serve - IPv4 address', () async { + when(mockProcessUtils.start(any)).thenAnswer((_) { + return Future<Process>.value(createMockProcess()); + }); + + await FuchsiaPM().serve('<repo>', '127.0.0.1', 43819); + + verify(mockProcessUtils.start(<String>[ + 'pm', + 'serve', + '-repo', + '<repo>', + '-l', + '127.0.0.1:43819', + ])).called(1); + }, overrides: <Type, Generator>{ + FuchsiaArtifacts: () => mockFuchsiaArtifacts, + ProcessUtils: () => mockProcessUtils, + }); + + testUsingContext('serve - IPv6 address', () async { + when(mockProcessUtils.start(any)).thenAnswer((_) { + return Future<Process>.value(createMockProcess()); + }); + + await FuchsiaPM().serve('<repo>', 'fe80::ec4:7aff:fecc:ea8f%eno2', 43819); + + verify(mockProcessUtils.start(<String>[ + 'pm', + 'serve', + '-repo', + '<repo>', + '-l', + '[fe80::ec4:7aff:fecc:ea8f%25eno2]:43819', + ])).called(1); + }, overrides: <Type, Generator>{ + FuchsiaArtifacts: () => mockFuchsiaArtifacts, + ProcessUtils: () => mockProcessUtils, + }); + }); +} + +class MockFuchsiaArtifacts extends Mock implements FuchsiaArtifacts {} +class MockProcessUtils extends Mock implements ProcessUtils {} +class MockFile extends Mock implements File {} +class MockProcess extends Mock implements Process {}