Windows, JNI: shorten the cwd for CreateProcess
The hard limit for SetCurrentDirectory{A,W} is
MAX_PATH-1, even with UNC prefix, therefore a
process' cwd may also not be longer than that.
See https://github.com/bazelbuild/bazel/issues/2107
See https://github.com/bazelbuild/bazel/issues/2406
See https://github.com/bazelbuild/bazel/issues/2181
--
PiperOrigin-RevId: 149290147
MOS_MIGRATED_REVID=149290147
diff --git a/src/main/native/windows_processes.cc b/src/main/native/windows_processes.cc
index a014a8c..3165b38 100644
--- a/src/main/native/windows_processes.cc
+++ b/src/main/native/windows_processes.cc
@@ -184,7 +184,15 @@
AddUncPrefixMaybe(GetJavaWstring(env, java_stdout_redirect));
std::wstring stderr_redirect =
AddUncPrefixMaybe(GetJavaWstring(env, java_stderr_redirect));
- std::string cwd = GetJavaUTFString(env, java_cwd);
+ std::string cwd;
+ error_msg = windows_util::AsShortPath(
+ GetJavaUTFString(env, java_cwd),
+ [env, java_cwd]() { return GetJavaWstring(env, java_cwd); },
+ &cwd);
+ if (!error_msg.empty()) {
+ result->error_ = error_msg;
+ return PtrAsJlong(result);
+ }
std::unique_ptr<char[]> mutable_commandline(new char[commandline.size() + 1]);
strncpy(mutable_commandline.get(), commandline.c_str(),
diff --git a/src/main/native/windows_util.cc b/src/main/native/windows_util.cc
index 4223d33..cc0d029 100644
--- a/src/main/native/windows_util.cc
+++ b/src/main/native/windows_util.cc
@@ -64,9 +64,8 @@
*result = string("\"") + path + "\"";
}
-string AsExecutablePathForCreateProcess(const string& path,
- function<wstring()> path_as_wstring,
- string* result) {
+string AsShortPath(const string& path, function<wstring()> path_as_wstring,
+ string* result) {
if (path.empty()) {
return string("argv[0] should not be empty");
}
@@ -93,10 +92,7 @@
// Fast-track: the path is already short.
if (path.size() < MAX_PATH) {
- // Quote the path in case it's something like "c:\foo\app name.exe".
- // Do this unconditionally, there's no harm in quoting. Quotes are not
- // allowed inside paths so we don't need to escape quotes.
- QuotePath(path, result);
+ *result = path;
return "";
}
// At this point we know that the path is at least MAX_PATH long and that it's
@@ -139,8 +135,21 @@
}
mbs_short[mbs_size] = 0;
- QuotePath(mbs_short, result);
+ *result = mbs_short;
return "";
}
+string AsExecutablePathForCreateProcess(const string& path,
+ function<wstring()> path_as_wstring,
+ string* result) {
+ string error = AsShortPath(path, path_as_wstring, result);
+ if (error.empty()) {
+ // Quote the path in case it's something like "c:\foo\app name.exe".
+ // Do this unconditionally, there's no harm in quoting. Quotes are not
+ // allowed inside paths so we don't need to escape quotes.
+ QuotePath(*result, result);
+ }
+ return error;
+}
+
} // namespace windows_util
diff --git a/src/main/native/windows_util.h b/src/main/native/windows_util.h
index a79d9dd..ea632e7 100644
--- a/src/main/native/windows_util.h
+++ b/src/main/native/windows_util.h
@@ -48,6 +48,10 @@
string GetLastErrorString(const string& cause);
+// Same as `AsExecutablePathForCreateProcess` except it won't quote the result.
+string AsShortPath(const string& path, function<wstring()> path_as_wstring,
+ string* result);
+
// Computes a path suitable as the executable part in CreateProcessA's cmdline.
//
// The null-terminated executable path for CreateProcessA has to fit into