Issue 34152. Verify file paths and report INVALID_FILE_PATH_FORMAT.

R=brianwilkerson@google.com, paulberry@google.com

Bug: https://github.com/dart-lang/sdk/issues/34152
Change-Id: I4a5f3634c342fbcfb3bf39c060cc658d87306312
Reviewed-on: https://dart-review.googlesource.com/c/90840
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index f876be1..aff4e6b 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -346,6 +346,12 @@
     });
   }
 
+  /// Return `true` if the [path] is both absolute and normalized.
+  bool isAbsoluteAndNormalized(String path) {
+    var pathContext = resourceProvider.pathContext;
+    return pathContext.isAbsolute(path) && pathContext.normalize(path) == path;
+  }
+
   /// Return `true` if analysis is complete.
   bool isAnalysisComplete() {
     return !analysisDriverScheduler.isAnalyzing;
@@ -377,6 +383,16 @@
     channel.sendResponse(response);
   }
 
+  /// If the [path] is not a valid file path, that is absolute and normalized,
+  /// send an error response, and return `true`. If OK then return `false`.
+  bool sendResponseErrorIfInvalidFilePath(Request request, String path) {
+    if (!isAbsoluteAndNormalized(path)) {
+      sendResponse(Response.invalidFilePathFormat(request, path));
+      return true;
+    }
+    return false;
+  }
+
   /// Sends a `server.error` notification.
   void sendServerErrorNotification(
     String message,
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 9d2cbe9..6886c65 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -47,6 +47,11 @@
    */
   Future<void> getErrors(Request request) async {
     String file = new AnalysisGetErrorsParams.fromRequest(request).file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     ResolvedUnitResult result = await server.getResolvedUnit(file);
 
     if (result?.state != ResultState.VALID) {
@@ -70,9 +75,14 @@
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     var params = new AnalysisGetHoverParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
 
     // Prepare the resolved units.
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     CompilationUnit unit = result?.unit;
 
     // Prepare the hovers.
@@ -96,12 +106,17 @@
   Future<void> getImportedElements(Request request) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
-    AnalysisGetImportedElementsParams params =
-        new AnalysisGetImportedElementsParams.fromRequest(request);
+    var params = new AnalysisGetImportedElementsParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     //
     // Prepare the resolved unit.
     //
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result?.state != ResultState.VALID) {
       server.sendResponse(new Response.getImportedElementsInvalidFile(request));
       return;
@@ -160,6 +175,10 @@
     int offset = params.offset;
     int length = params.length;
 
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     AnalysisDriver driver = server.getAnalysisDriver(file);
     if (driver == null) {
       server.sendResponse(new Response.getNavigationInvalidFile(request));
@@ -242,9 +261,14 @@
    */
   Future<void> getSignature(Request request) async {
     var params = new AnalysisGetSignatureParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
 
     // Prepare the resolved units.
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
 
     if (result?.state != ResultState.VALID) {
       server.sendResponse(new Response.getSignatureInvalidFile(request));
@@ -388,6 +412,12 @@
   Response setPriorityFiles(Request request) {
     var params = new AnalysisSetPriorityFilesParams.fromRequest(request);
 
+    for (var file in params.files) {
+      if (!server.isAbsoluteAndNormalized(file)) {
+        return Response.invalidFilePathFormat(request, file);
+      }
+    }
+
     if (server.options.enableUXExperiment1) {
       // If this experiment is enabled, set the analysis root to be the
       // containing directory.
@@ -445,6 +475,15 @@
    */
   Response setSubscriptions(Request request) {
     var params = new AnalysisSetSubscriptionsParams.fromRequest(request);
+
+    for (var fileList in params.subscriptions.values) {
+      for (var file in fileList) {
+        if (!server.isAbsoluteAndNormalized(file)) {
+          return Response.invalidFilePathFormat(request, file);
+        }
+      }
+    }
+
     // parse subscriptions
     Map<AnalysisService, Set<String>> subMap = mapMap(params.subscriptions,
         valueCallback: (List<String> subscriptions) => subscriptions.toSet());
@@ -466,6 +505,13 @@
    */
   Response updateContent(Request request) {
     var params = new AnalysisUpdateContentParams.fromRequest(request);
+
+    for (var file in params.files.keys) {
+      if (!server.isAbsoluteAndNormalized(file)) {
+        return Response.invalidFilePathFormat(request, file);
+      }
+    }
+
     server.updateContent(request.id, params.files);
     //
     // Forward the request to the plugins.
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 2b61900..c70db3b 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -170,10 +170,14 @@
     // extract and validate params
     CompletionGetSuggestionsParams params =
         new CompletionGetSuggestionsParams.fromRequest(request);
-    String filePath = params.file;
+    String file = params.file;
     int offset = params.offset;
 
-    ResolvedUnitResult result = await server.getResolvedUnit(filePath);
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
 
     if (result?.state == ResultState.VALID) {
       if (offset < 0 || offset > result.content.length) {
@@ -185,7 +189,7 @@
         return;
       }
 
-      recordRequest(performance, filePath, result.content, offset);
+      recordRequest(performance, file, result.content, offset);
     }
     CompletionRequestImpl completionRequest =
         new CompletionRequestImpl(result, offset, performance);
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 2e1f6e2..f692c76 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -165,6 +165,10 @@
     int offset = params.offset;
     int length = params.length;
 
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     List<SourceChange> changes = <SourceChange>[];
     //
     // Allow plugins to start computing assists.
@@ -228,6 +232,11 @@
     EditGetFixesParams params = new EditGetFixesParams.fromRequest(request);
     String file = params.file;
     int offset = params.offset;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     //
     // Allow plugins to start computing fixes.
     //
@@ -277,9 +286,15 @@
     server.options.analytics?.sendEvent('edit', 'getPostfixCompletion');
 
     var params = new EditGetPostfixCompletionParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     SourceChange change;
 
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result != null) {
       PostfixCompletionContext context = new PostfixCompletionContext(
         result,
@@ -303,10 +318,17 @@
   Future getStatementCompletion(Request request) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
+
     var params = new EditGetStatementCompletionParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     SourceChange change;
 
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result != null) {
       var context = new StatementCompletionContext(result, params.offset);
       StatementCompletionProcessor processor =
@@ -377,12 +399,18 @@
   Future<void> importElements(Request request) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
-    EditImportElementsParams params =
-        new EditImportElementsParams.fromRequest(request);
+
+    var params = new EditImportElementsParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     //
     // Prepare the resolved unit.
     //
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result == null) {
       server.sendResponse(new Response.importElementsInvalidFile(request));
     }
@@ -415,9 +443,15 @@
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     var params = new EditGetPostfixCompletionParams.fromRequest(request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     bool value = false;
 
-    ResolvedUnitResult result = await server.getResolvedUnit(params.file);
+    ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result != null) {
       var context = new PostfixCompletionContext(
         result,
@@ -452,12 +486,16 @@
     server.options.analytics?.sendEvent('edit', 'organizeDirectives');
 
     var params = new EditOrganizeDirectivesParams.fromRequest(request);
-    // prepare file
-    String file = params.file;
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
     if (!engine.AnalysisEngine.isDartFileName(file)) {
       server.sendResponse(new Response.fileNotAnalyzed(request, file));
       return;
     }
+
     // Prepare the file information.
     ResolvedUnitResult result = await server.getResolvedUnit(file);
     if (result == null) {
@@ -487,19 +525,23 @@
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     var params = new EditSortMembersParams.fromRequest(request);
-    // prepare file
-    String file = params.file;
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
     if (!engine.AnalysisEngine.isDartFileName(file)) {
       server.sendResponse(new Response.sortMembersInvalidFile(request));
       return;
     }
+
     // Prepare the file information.
-    var driver = server.getAnalysisDriver(file);
-    ParsedUnitResult result = await driver?.parseFile(file);
+    ParsedUnitResult result = await server.getParsedUnit(file);
     if (result == null) {
       server.sendResponse(new Response.fileNotAnalyzed(request, file));
       return;
     }
+
     int fileStamp = -1;
     String code = result.content;
     CompilationUnit unit = result.unit;
@@ -560,13 +602,15 @@
   }
 
   Future _getAvailableRefactoringsImpl(Request request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    // prepare parameters
     var params = new EditGetAvailableRefactoringsParams.fromRequest(request);
     String file = params.file;
     int offset = params.offset;
     int length = params.length;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
     // add refactoring kinds
     List<RefactoringKind> kinds = <RefactoringKind>[];
     // Check nodes.
@@ -731,6 +775,11 @@
         EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST, EMPTY_PROBLEM_LIST);
     // process the request
     var params = new EditGetRefactoringParams.fromRequest(_request);
+    var file = params.file;
+
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
 
     if (params.kind != null) {
       server.options.analytics
@@ -740,7 +789,7 @@
     runZoned(() async {
       // TODO(brianwilkerson) Determine whether this await is necessary.
       await null;
-      await _init(params.kind, params.file, params.offset, params.length);
+      await _init(params.kind, file, params.offset, params.length);
       if (initStatus.hasFatalError) {
         feedback = null;
         _sendResultResponse();
diff --git a/pkg/analysis_server/test/analysis/get_errors_test.dart b/pkg/analysis_server/test/analysis/get_errors_test.dart
index db150ad..b32c59d 100644
--- a/pkg/analysis_server/test/analysis/get_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/get_errors_test.dart
@@ -12,6 +12,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -95,6 +96,24 @@
     }
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = _createGetErrorsRequest('test.dart');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure(requestId, RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = _createGetErrorsRequest(convertPath('/foo/../bar/test.dart'));
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure(requestId, RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_noErrors() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index faadc26..7dc1119 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -10,6 +10,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -416,6 +417,26 @@
     expect(hover.parameter, 'double myParameter');
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new AnalysisGetHoverParams('test.dart', 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new AnalysisGetHoverParams(convertPath('/foo/../bar/test.dart'), 0)
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_localVariable_declaration() async {
     addTestFile('''
 library my.library;
diff --git a/pkg/analysis_server/test/analysis/get_navigation_test.dart b/pkg/analysis_server/test/analysis/get_navigation_test.dart
index cc31c34..b99aa74 100644
--- a/pkg/analysis_server/test/analysis/get_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/get_navigation_test.dart
@@ -9,6 +9,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../mocks.dart';
 import 'notification_navigation_test.dart';
 
 main() {
@@ -129,6 +130,25 @@
     expect(testTargets[0].kind, ElementKind.LIBRARY);
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = _createGetNavigationRequest('test.dart', 0, 0);
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure(requestId, RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        _createGetNavigationRequest(convertPath('/foo/../bar/test.dart'), 0, 0);
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure(requestId, RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_multipleRegions() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index e91c889..4242908 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -11,6 +11,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -131,13 +132,6 @@
         equals(RequestErrorCode.GET_SIGNATURE_UNKNOWN_FUNCTION));
   }
 
-  test_error_file_invalid_path() async {
-    var result = await prepareRawSignatureAt(0, file: ':\\/?*');
-    expect(result.error, isNotNull);
-    expect(
-        result.error.code, equals(RequestErrorCode.GET_SIGNATURE_INVALID_FILE));
-  }
-
   test_error_file_not_analyzed() async {
     var result = await prepareRawSignatureAt(0,
         file: convertPath('/not/in/project.dart'));
@@ -407,6 +401,26 @@
     expect(result.parameters, hasLength(0));
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new AnalysisGetSignatureParams('test.dart', 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new AnalysisGetSignatureParams(convertPath('/foo/../bar/test.dart'), 0)
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_method_instance() async {
     addTestFile('''
 /// MyClass doc
diff --git a/pkg/analysis_server/test/analysis/set_priority_files_test.dart b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
index bb6530d..f6bcb09 100644
--- a/pkg/analysis_server/test/analysis/set_priority_files_test.dart
+++ b/pkg/analysis_server/test/analysis/set_priority_files_test.dart
@@ -105,6 +105,26 @@
     _verifyPriorityFiles(sampleFile);
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request =
+        new AnalysisSetPriorityFilesParams(['test.dart']).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new AnalysisSetPriorityFilesParams(
+        [convertPath('/foo/../bar/test.dart')]).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_sentToPlugins() async {
     addTestFile('');
     // set priority files
diff --git a/pkg/analysis_server/test/analysis/update_content_test.dart b/pkg/analysis_server/test/analysis/update_content_test.dart
index 5ab9a4e..9245872 100644
--- a/pkg/analysis_server/test/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/analysis/update_content_test.dart
@@ -14,6 +14,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -60,6 +61,28 @@
     }
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new AnalysisUpdateContentParams(
+      {'test.dart': AddContentOverlay('')},
+    ).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new AnalysisUpdateContentParams(
+      {convertPath('/foo/../bar/test.dart'): AddContentOverlay('')},
+    ).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_multiple_contexts() async {
     String project1path = convertPath('/project1');
     String project2path = convertPath('/project2');
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index f22f2f2..4749ab7 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -19,6 +19,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'domain_completion_util.dart';
+import 'mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -548,6 +549,27 @@
     });
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request =
+        new CompletionGetSuggestionsParams('test.dart', 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new CompletionGetSuggestionsParams(
+            convertPath('/foo/../bar/test.dart'), 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_invocation() {
     addTestFile('class A {b() {}} main() {A a; a.^}');
     return getSuggestions().then((_) {
diff --git a/pkg/analysis_server/test/edit/assists_test.dart b/pkg/analysis_server/test/edit/assists_test.dart
index d8a77f0..51c4da0 100644
--- a/pkg/analysis_server/test/edit/assists_test.dart
+++ b/pkg/analysis_server/test/edit/assists_test.dart
@@ -16,6 +16,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -68,6 +69,26 @@
     _assertHasChange(message, 'xmain() {}');
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditGetAssistsParams('test.dart', 0, 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new EditGetAssistsParams(convertPath('/foo/../bar/test.dart'), 0, 0)
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_removeTypeAnnotation() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index c9c5eaa..4c48892 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -16,6 +16,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -96,6 +97,26 @@
     }
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditGetFixesParams('test.dart', 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new EditGetFixesParams(convertPath('/foo/../bar/test.dart'), 0)
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_overlayOnlyFile() async {
     createProject();
     testCode = '''
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index e8424aa..010b576 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -62,6 +62,26 @@
         response, isResponseFailure('0', RequestErrorCode.FILE_NOT_ANALYZED));
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditOrganizeDirectivesParams('test.dart').toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new EditOrganizeDirectivesParams(convertPath('/foo/../bar/test.dart'))
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   Future test_OK_remove_duplicateImports_withSamePrefix() {
     addTestFile('''
 library lib;
diff --git a/pkg/analysis_server/test/edit/postfix_completion_test.dart b/pkg/analysis_server/test/edit/postfix_completion_test.dart
index 00139e5..c8cede9 100644
--- a/pkg/analysis_server/test/edit/postfix_completion_test.dart
+++ b/pkg/analysis_server/test/edit/postfix_completion_test.dart
@@ -10,6 +10,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -45,6 +46,27 @@
 ''');
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditGetPostfixCompletionParams('test.dart', '.for', 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new EditGetPostfixCompletionParams(
+            convertPath('/foo/../bar/test.dart'), '.for', 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   void _assertHasChange(String message, String expectedCode, [Function cmp]) {
     if (change.message == message) {
       if (!change.edits.isEmpty) {
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index da70280..df6558d 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -352,6 +352,32 @@
 ''');
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditGetRefactoringParams(
+            RefactoringKind.EXTRACT_LOCAL_VARIABLE, 'test.dart', 0, 0, true)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new EditGetRefactoringParams(
+            RefactoringKind.EXTRACT_LOCAL_VARIABLE,
+            convertPath('/foo/../bar/test.dart'),
+            0,
+            0,
+            true)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_names() async {
     addTestFile('''
 class TreeItem {}
@@ -901,6 +927,27 @@
     expect(kinds, contains(RefactoringKind.EXTRACT_WIDGET));
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditGetAvailableRefactoringsParams('test.dart', 0, 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new EditGetAvailableRefactoringsParams(
+            convertPath('/foo/../bar/test.dart'), 0, 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   Future test_rename_hasElement_class() {
     return assertHasRenameRefactoring('''
 class Test {}
diff --git a/pkg/analysis_server/test/edit/sort_members_test.dart b/pkg/analysis_server/test/edit/sort_members_test.dart
index 04828b6..a065d15f 100644
--- a/pkg/analysis_server/test/edit/sort_members_test.dart
+++ b/pkg/analysis_server/test/edit/sort_members_test.dart
@@ -62,6 +62,26 @@
         isResponseFailure('0', RequestErrorCode.SORT_MEMBERS_INVALID_FILE));
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request = new EditSortMembersParams('test.dart').toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request =
+        new EditSortMembersParams(convertPath('/foo/../bar/test.dart'))
+            .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_OK_afterWaitForAnalysis() async {
     addTestFile('''
 class C {}
diff --git a/pkg/analysis_server/test/edit/statement_completion_test.dart b/pkg/analysis_server/test/edit/statement_completion_test.dart
index 50f834b..4b381be 100644
--- a/pkg/analysis_server/test/edit/statement_completion_test.dart
+++ b/pkg/analysis_server/test/edit/statement_completion_test.dart
@@ -10,6 +10,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../analysis_abstract.dart';
+import '../mocks.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -28,6 +29,27 @@
     handler = new EditDomainHandler(server);
   }
 
+  test_invalidFilePathFormat_notAbsolute() async {
+    var request =
+        new EditGetStatementCompletionParams('test.dart', 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
+  test_invalidFilePathFormat_notNormalized() async {
+    var request = new EditGetStatementCompletionParams(
+            convertPath('/foo/../bar/test.dart'), 0)
+        .toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.INVALID_FILE_PATH_FORMAT),
+    );
+  }
+
   test_plainEnterFromStart() async {
     addTestFile('''
 main() {