From 78e65f240c88636c5f1857a65010c145084b0a44 Mon Sep 17 00:00:00 2001 From: Fontlos <56759523+fontlos@users.noreply.github.com> Date: Tue, 20 May 2025 17:40:05 +0800 Subject: [PATCH] fix(cli): prevent linker argument overflow on Windows (#4126) --- packages/cli/src/cli/link.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/cli/link.rs b/packages/cli/src/cli/link.rs index a32cf6e42..07a1a3f4f 100644 --- a/packages/cli/src/cli/link.rs +++ b/packages/cli/src/cli/link.rs @@ -122,7 +122,7 @@ impl LinkAction { /// The file will be given by the dx-magic-link-arg env var itself, so we use /// it both for determining if we should act as a linker and the for the file name itself. async fn run_link_inner(self) -> Result<()> { - let mut args: Vec<_> = std::env::args().collect(); + let mut args: Vec<_> = std::env::args().skip(1).collect(); if args.is_empty() { return Ok(()); } @@ -131,16 +131,18 @@ impl LinkAction { // Write the linker args to a file for the main process to read // todo: we might need to encode these as escaped shell words in case newlines are passed - std::fs::write(self.link_args_file, args.join("\n"))?; + std::fs::write(&self.link_args_file, args.join("\n"))?; // If there's a linker specified, we use that. Otherwise, we write a dummy object file to satisfy // any post-processing steps that rustc does. match self.linker { Some(linker) => { - let res = std::process::Command::new(linker) - .args(args.iter().skip(1)) - .output() - .expect("Failed to run linker"); + let mut cmd = std::process::Command::new(linker); + match cfg!(target_os = "windows") { + true => cmd.arg(format!("@{}", &self.link_args_file.display())), + false => cmd.args(args), + }; + let res = cmd.output().expect("Failed to run linker"); if !res.stderr.is_empty() || !res.stdout.is_empty() { _ = std::fs::create_dir_all(self.link_err_file.parent().unwrap());