Skip to content

Commit 48674f2

Browse files
committed
fix win segv
1 parent 7114794 commit 48674f2

1 file changed

Lines changed: 77 additions & 18 deletions

File tree

bazel/ocx/private/launcher/launcher.cc

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
#include <string>
33
#include <unordered_map>
44
#include <cstring>
5+
#include <vector>
56
#include "rules_cc/cc/runfiles/runfiles.h"
67

78
#ifdef _WIN32
8-
#include <process.h>
9+
#include <Windows.h>
910
#else
1011
#include <unistd.h>
1112
#endif
@@ -14,8 +15,7 @@ using rules_cc::cc::runfiles::Runfiles;
1415

1516
const char* env_vars[] = ENV;
1617

17-
18-
static const char** build_merged_envp(char *envp[], const std::string& layer_dir)
18+
static std::vector<std::string> build_merged_envp(char *envp[], const std::string& layer_dir)
1919
{
2020
std::unordered_map<std::string, std::string> merged_env;
2121
for (char** env = envp; env && *env; ++env)
@@ -28,6 +28,9 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
2828
}
2929

3030
std::string key = current.substr(0, separator);
31+
#ifdef _WIN32
32+
for (auto& c : key) c = toupper((unsigned char)c);
33+
#endif
3134
merged_env[key] = current.substr(separator + 1);
3235
}
3336

@@ -41,6 +44,9 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
4144
}
4245

4346
std::string key = current.substr(0, separator);
47+
#ifdef _WIN32
48+
for (auto& c : key) c = toupper((unsigned char)c);
49+
#endif
4450
std::string value = current.substr(separator + 1);
4551

4652
// Replace ${installPath} with the actual layer directory path.
@@ -64,16 +70,12 @@ static const char** build_merged_envp(char *envp[], const std::string& layer_dir
6470
}
6571

6672
// Convert the merged environment map back to an array of C strings.
67-
const char** merged_envp = new const char*[merged_env.size() + 1];
68-
size_t i = 0;
73+
std::vector<std::string> merged_envp;
74+
merged_envp.reserve(merged_env.size());
6975
for (auto& [key, value] : merged_env)
7076
{
71-
std::string entry = key + "=" + value;
72-
char* buffer = new char[entry.size() + 1];
73-
memcpy(buffer, entry.c_str(), entry.size() + 1);
74-
merged_envp[i++] = buffer;
77+
merged_envp.push_back(key + "=" + value);
7578
}
76-
merged_envp[i] = nullptr;
7779
return merged_envp;
7880
}
7981

@@ -82,7 +84,6 @@ int main(int argc, char *argv[], char *envp[])
8284
(void)argc;
8385

8486
std::string error;
85-
8687
// Resolve the path to the executable in the runfiles structure
8788
auto runfiles = std::unique_ptr<Runfiles>(
8889
Runfiles::Create(argv[0], BAZEL_CURRENT_REPOSITORY, &error));
@@ -93,7 +94,6 @@ int main(int argc, char *argv[], char *envp[])
9394
}
9495
std::string bin_path = BIN_PATH;
9596
std::string path = runfiles->Rlocation(bin_path);
96-
9797
// Resolve the image layer root directory in the runfiles structure
9898
auto layer_dir_pos = bin_path.find("/layer/");
9999
if (layer_dir_pos == std::string::npos) {
@@ -102,19 +102,78 @@ int main(int argc, char *argv[], char *envp[])
102102
}
103103
auto bin_path_in_layer_length = bin_path.length() - layer_dir_pos - 7;
104104
std::string layer_dir = path.substr(0, path.length() - bin_path_in_layer_length);
105-
106-
const char** merged_envp = build_merged_envp(envp, layer_dir);
105+
std::vector<std::string> merged_envp = build_merged_envp(envp, layer_dir);
107106

108107
#ifdef _WIN32
109-
int res = _execve(path.c_str(), argv, (char *const *) merged_envp);
110-
#else
111-
int res = execve(path.c_str(), argv, (char *const *) merged_envp);
112-
#endif
108+
// Build command line
109+
std::string cmdline = "\"" + path + "\"";
110+
for (int i = 1; argv[i] != nullptr; ++i) {
111+
cmdline += " \"";
112+
cmdline += argv[i];
113+
cmdline += "\"";
114+
}
113115

116+
// Build environment block (double-null-terminated)
117+
size_t env_block_len = 0;
118+
for (const auto& env : merged_envp) {
119+
env_block_len += env.size() + 1;
120+
}
121+
env_block_len += 1; // final null
122+
char* env_block = new char[env_block_len];
123+
char* p = env_block;
124+
for (const auto& env : merged_envp) {
125+
size_t len = env.size();
126+
memcpy(p, env.c_str(), len);
127+
p += len;
128+
*p++ = '\0';
129+
}
130+
*p = '\0';
131+
132+
STARTUPINFOA si;
133+
PROCESS_INFORMATION pi;
134+
ZeroMemory(&si, sizeof(si));
135+
si.cb = sizeof(si);
136+
ZeroMemory(&pi, sizeof(pi));
137+
138+
BOOL success = CreateProcessA(
139+
path.c_str(),
140+
(LPSTR)cmdline.c_str(),
141+
NULL,
142+
NULL,
143+
FALSE,
144+
0,
145+
env_block,
146+
NULL,
147+
&si,
148+
&pi
149+
);
150+
if (!success) {
151+
fprintf(stderr, "ERROR: failed to execute '%s' (CreateProcess failed)\n", path.c_str());
152+
delete[] env_block;
153+
return 1;
154+
}
155+
// Wait for process to finish
156+
WaitForSingleObject(pi.hProcess, INFINITE);
157+
DWORD exit_code = 0;
158+
GetExitCodeProcess(pi.hProcess, &exit_code);
159+
CloseHandle(pi.hProcess);
160+
CloseHandle(pi.hThread);
161+
delete[] env_block;
162+
return (int)exit_code;
163+
#else
164+
// Build char* array for execve
165+
std::vector<char*> envp_cstrs;
166+
envp_cstrs.reserve(merged_envp.size() + 1);
167+
for (const auto& env : merged_envp) {
168+
envp_cstrs.push_back(const_cast<char*>(env.c_str()));
169+
}
170+
envp_cstrs.push_back(nullptr);
171+
int res = execve(path.c_str(), argv, envp_cstrs.data());
114172
if (res == -1)
115173
{
116174
fprintf(stderr, "ERROR: failed to execute '%s'\n", path.c_str());
117175
return 1;
118176
}
119177
return 0;
178+
#endif
120179
}

0 commit comments

Comments
 (0)