22
22
#include " boost/interprocess/ipc/message_queue.hpp"
23
23
#include " boost/process/child.hpp"
24
24
#include " boost/process/io.hpp"
25
+ #include " boost/process/search_path.hpp"
25
26
#include " rapidjson/document.h"
26
27
#include " rapidjson/error/en.h"
27
28
#include " rapidjson/filereadstream.h"
@@ -111,7 +112,7 @@ struct WorkerInfo {
111
112
};
112
113
113
114
struct DriverOptions {
114
- std::string workerExecutablePath;
115
+ AbsolutePath workerExecutablePath;
115
116
RootPath projectRootPath;
116
117
AbsolutePath compdbPath;
117
118
AbsolutePath indexOutputPath;
@@ -129,7 +130,7 @@ struct DriverOptions {
129
130
std::vector<std::string> originalArgv;
130
131
131
132
explicit DriverOptions (std::string driverId, const CliOptions &cliOpts)
132
- : workerExecutablePath(cliOpts.scipClangExecutablePath ),
133
+ : workerExecutablePath(),
133
134
projectRootPath(AbsolutePath(" /" ), RootKind::Project), compdbPath(),
134
135
indexOutputPath(), numWorkers(cliOpts.numWorkers),
135
136
receiveTimeout(cliOpts.receiveTimeout),
@@ -158,6 +159,28 @@ struct DriverOptions {
158
159
RootRelativePathRef (path, RootKind::Project));
159
160
};
160
161
162
+ // Strictly speaking, there is a TOCTOU problem here, as scip-clang
163
+ // can go missing between this check and the actual execve invocation
164
+ // when spawning a worker, but it's simpler to check this here and
165
+ // provide a nicer error message.
166
+ if (cliOpts.scipClangExecutablePath .find (
167
+ std::filesystem::path::preferred_separator)
168
+ == std::string::npos) {
169
+ auto newPath =
170
+ boost::process::search_path (cliOpts.scipClangExecutablePath );
171
+ if (newPath.empty ()) {
172
+ spdlog::error (" scip-clang needs to be able to re-invoke itself,"
173
+ " but couldn't find scip-clang on PATH."
174
+ " Hint: Use a modified PATH to invoke scip-clang,"
175
+ " or invoke scip-clang using an absolute path" );
176
+ std::exit (1 );
177
+ }
178
+ this ->workerExecutablePath = AbsolutePath (std::string (newPath.native ()));
179
+ } else {
180
+ setAbsolutePath (cliOpts.scipClangExecutablePath ,
181
+ this ->workerExecutablePath );
182
+ }
183
+
161
184
setAbsolutePath (cliOpts.indexOutputPath , this ->indexOutputPath );
162
185
setAbsolutePath (cliOpts.compdbPath , this ->compdbPath );
163
186
@@ -754,7 +777,7 @@ class Driver {
754
777
755
778
boost::process::child spawnWorker (WorkerId workerId) {
756
779
std::vector<std::string> args;
757
- args.push_back (this ->options .workerExecutablePath );
780
+ args.push_back (this ->options .workerExecutablePath . asStringRef () );
758
781
args.push_back (" --worker-mode=ipc" );
759
782
args.push_back (fmt::format (" --driver-id={}" , this ->id ));
760
783
args.push_back (fmt::format (" --worker-id={}" , workerId));
0 commit comments