[native assets] Propagate OS error on invocation via `PATHEXT` Native assets resolution will now fail with an error message similar to: ``` Invalid argument(s): Couldn't resolve native function '<...>' in '<...>' : Failed to canonicalize the script uri '<path without extension>'. OS error: 'The system cannot find the file specified. ``` Supporting PATHEXT will be done in a follow up CL. TEST=pkg/dartdev/test/native_assets/build_test.dart Bug: https://github.com/dart-lang/sdk/issues/60946 Change-Id: I7db07b6c310ca8badd509c1d5d0595f671f1062d Cq-Include-Trybots: luci.dart.try:pkg-win-release-arm64-try,pkg-win-release-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/435162 Reviewed-by: Michael Goderbauer <goderbauer@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
diff --git a/pkg/dartdev/test/native_assets/build_test.dart b/pkg/dartdev/test/native_assets/build_test.dart index bef7771..bd59b50 100644 --- a/pkg/dartdev/test/native_assets/build_test.dart +++ b/pkg/dartdev/test/native_assets/build_test.dart
@@ -66,6 +66,31 @@ final link = Link.fromUri( tempUri.resolve(OS.current.executableFileName('my_link'))); await link.create(absoluteExeUri.toFilePath()); + if (OS.current == OS.windows) { + for (final exeUri in [ + removeDotExe(link.uri), + removeDotExe(absoluteExeUri), + removeDotExe(relativeExeUri), + ]) { + final result = await runProcess( + executable: exeUri, + arguments: [], + workingDirectory: dartAppUri, + logger: logger, + ); + // TODO(https://dartbug.com/60946): Support PATHEXT. + expect(result.exitCode, isNot(0)); + expect( + result.stderr, + stringContainsInOrder( + [ + 'Failed to canonicalize the script uri', + 'The system cannot find the file specified.', + ], + ), + ); + } + } for (final exeUri in [ absoluteExeUri, relativeExeUri, @@ -354,3 +379,12 @@ } } } + +Uri removeDotExe(Uri withExe) { + final exeName = withExe.pathSegments.lastWhere((e) => e.isNotEmpty); + if (!exeName.endsWith('.exe')) { + throw StateError('Expected executable to end in .exe, got $exeName'); + } + final fileName = exeName.replaceAll('.exe', ''); + return withExe.resolve(fileName); +}
diff --git a/runtime/bin/native_assets_api_impl.cc b/runtime/bin/native_assets_api_impl.cc index 3834c68..1595d59 100644 --- a/runtime/bin/native_assets_api_impl.cc +++ b/runtime/bin/native_assets_api_impl.cc
@@ -4,6 +4,7 @@ #include "include/bin/native_assets_api.h" +#include "bin/utils.h" #include "platform/globals.h" #include "platform/utils.h" @@ -54,7 +55,7 @@ // Get a file uri with only forward slashes from the script path. // Returned string must be freed by caller. -CStringUniquePtr CleanScriptUri(const char* script_uri) { +CStringUniquePtr CleanScriptUri(const char* script_uri, char** error) { CStringUniquePtr script_path; if (strlen(script_uri) > file_schema_length && @@ -68,8 +69,15 @@ } // Resolve symlinks. - char canon_path[PATH_MAX]; - File::GetCanonicalPath(nullptr, script_path.get(), canon_path, PATH_MAX); + const char* canon_path = File::GetCanonicalPath(nullptr, script_path.get()); + if (canon_path == nullptr) { + OSError os_error; + SET_ERROR_MSG( + error, + "Failed to canonicalize the script uri '%s'. OS error: '%s' (%i).", + script_path.get(), os_error.message(), os_error.code()); + return CStringUniquePtr(); + } // Convert path to Uri. Inspired by sdk/lib/core/uri.dart _makeFileUri. // Only has a single case, the path is always absolute and always a file. @@ -141,7 +149,10 @@ const char* script_uri, char** error) { void* handle = nullptr; - CStringUniquePtr platform_script_cstr = CleanScriptUri(script_uri); + CStringUniquePtr platform_script_cstr = CleanScriptUri(script_uri, error); + if (*error != nullptr) { + return nullptr; + } const intptr_t len = strlen(path); char* path_copy = reinterpret_cast<char*>(malloc(len + 1)); snprintf(path_copy, len + 1, "%s", path);