Skip to content

Commit d49974c

Browse files
committed
fix(installer): move set_var before tokio runtime and fix build.rs cross-compile
- Move VP_HOME set_var and resolve_install_dir to main() before the tokio multi-thread runtime is created, ensuring no other threads can race on env var access (fixes UB safety concern). - Use CARGO_CFG_TARGET_OS in build.rs instead of #[cfg(windows)] so the DLL security linker flag is correctly emitted when cross-compiling from a non-Windows host to a Windows target.
1 parent 2e2720b commit d49974c

File tree

2 files changed

+19
-17
lines changed

2 files changed

+19
-17
lines changed

crates/vite_installer/build.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ fn main() {
22
// On Windows, set DEPENDENTLOADFLAG to only search system32 for DLLs at load time.
33
// This prevents DLL hijacking when the installer is downloaded to a folder
44
// containing malicious DLLs (e.g. Downloads). Matches rustup's approach.
5-
#[cfg(windows)]
6-
println!("cargo:rustc-link-arg=/DEPENDENTLOADFLAG:0x800");
5+
// Use CARGO_CFG_TARGET_OS (not #[cfg(windows)]) so the flag is emitted
6+
// correctly when cross-compiling from a non-Windows host.
7+
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
8+
println!("cargo:rustc-link-arg=/DEPENDENTLOADFLAG:0x800");
9+
}
710
}

crates/vite_installer/src/main.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,32 +97,31 @@ fn main() {
9797

9898
let opts = cli::parse();
9999

100+
// Resolve install dir and set VP_HOME before starting the tokio runtime,
101+
// so the unsafe set_var runs while we're still single-threaded.
102+
let install_dir = match resolve_install_dir(&opts) {
103+
Ok(dir) => dir,
104+
Err(e) => {
105+
print_error(&format!("Failed to resolve install directory: {e}"));
106+
std::process::exit(1);
107+
}
108+
};
109+
// Safety: called in main() before any threads are spawned.
110+
unsafe { std::env::set_var("VP_HOME", install_dir.as_path()) };
111+
100112
let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap_or_else(|e| {
101113
print_error(&format!("Failed to create async runtime: {e}"));
102114
std::process::exit(1);
103115
});
104116

105-
let code = rt.block_on(run(opts));
117+
let code = rt.block_on(run(opts, install_dir));
106118
std::process::exit(code);
107119
}
108120

109121
#[allow(clippy::print_stdout, clippy::print_stderr)]
110-
async fn run(mut opts: cli::Options) -> i32 {
111-
let install_dir = match resolve_install_dir(&opts) {
112-
Ok(dir) => dir,
113-
Err(e) => {
114-
print_error(&format!("Failed to resolve install directory: {e}"));
115-
return 1;
116-
}
117-
};
122+
async fn run(mut opts: cli::Options, install_dir: AbsolutePathBuf) -> i32 {
118123
let install_dir_display = install_dir.as_path().to_string_lossy().to_string();
119124

120-
// Propagate the resolved install directory to child `vp` processes
121-
// (refresh_shims, create_env_files, install_production_deps) so they
122-
// find the correct home, especially for --install-dir overrides.
123-
// Safety: no other threads are reading env vars at this point.
124-
unsafe { std::env::set_var("VP_HOME", install_dir.as_path()) };
125-
126125
// Pre-compute Node.js manager default before showing the menu,
127126
// so the user sees the resolved value and can override it.
128127
if !opts.no_node_manager {

0 commit comments

Comments
 (0)