Skip to content

Commit

Permalink
rustdoc --test: Prevent reaching the maximum size of command-line b…
Browse files Browse the repository at this point in the history
…y using files for arguments if there are too many
  • Loading branch information
GuillaumeGomez committed Mar 22, 2024
1 parent eff958c commit 1a732c5
Showing 1 changed file with 51 additions and 7 deletions.
58 changes: 51 additions & 7 deletions src/librustdoc/doctest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use rustc_target::spec::{Target, TargetTriple};
use tempfile::Builder as TempFileBuilder;

use std::env;
use std::fs::File;
use std::io::{self, Write};
use std::panic;
use std::path::{Path, PathBuf};
Expand All @@ -31,6 +32,8 @@ use std::str;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};

use tempfile::tempdir;

use crate::clean::{types::AttributesExt, Attributes};
use crate::config::Options as RustdocOptions;
use crate::html::markdown::{self, ErrorCodes, Ignore, LangString};
Expand Down Expand Up @@ -348,13 +351,49 @@ fn run_test(
.unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc"));
let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary);
compiler.arg("--crate-type").arg("bin");
for cfg in &rustdoc_options.cfgs {
compiler.arg("--cfg").arg(&cfg);

let mut needs_unstable_options = false;
let mut written_cfg_args = false;
#[allow(unused_variables)]
let tmp_dir;

// If there are too many `cfg` arguments, instead of risking reaching `Command`'s limit on
// the number of arguments, we put them into a file which we then pass as `@` argument.
if rustdoc_options.cfgs.len() + rustdoc_options.check_cfgs.len() > 1_000
&& let Ok(temp_dir) = tempdir()
&& let file_path = temp_dir.path().join("cfgs")
&& let Ok(mut file) = File::create(&file_path)
{
let mut content = Vec::new();
for cfg in &rustdoc_options.cfgs {
content.push(format!("--cfg={cfg}"));
}
if !rustdoc_options.check_cfgs.is_empty() {
needs_unstable_options = true;
for check_cfg in &rustdoc_options.check_cfgs {
content.push(format!("--check-cfg={check_cfg}"));
}
}
let content = content.join("\n");
#[allow(unused_assignments)] // Needed for `tmp_dir = temp_dir`.
if file.write(content.as_bytes()).is_ok() {
// To prevent removing the temporary directory too soon.
tmp_dir = temp_dir;
written_cfg_args = true;
compiler.arg(&format!("@{}", file_path.display()));
}
}
if !rustdoc_options.check_cfgs.is_empty() {
compiler.arg("-Z").arg("unstable-options");
for check_cfg in &rustdoc_options.check_cfgs {
compiler.arg("--check-cfg").arg(&check_cfg);
// If there were not enough `cfg` argument to make a file, or the file creation failed,
// we use the usual `Command` API.
if !written_cfg_args {
for cfg in &rustdoc_options.cfgs {
compiler.arg("--cfg").arg(&cfg);
}
if !rustdoc_options.check_cfgs.is_empty() {
needs_unstable_options = true;
for check_cfg in &rustdoc_options.check_cfgs {
compiler.arg("--check-cfg").arg(&check_cfg);
}
}
}
if let Some(sysroot) = rustdoc_options.maybe_sysroot {
Expand All @@ -370,9 +409,14 @@ fn run_test(
if rustdoc_options.json_unused_externs.is_enabled() && !lang_string.compile_fail {
compiler.arg("--error-format=json");
compiler.arg("--json").arg("unused-externs");
compiler.arg("-Z").arg("unstable-options");
compiler.arg("-W").arg("unused_crate_dependencies");
needs_unstable_options = true;
}

if needs_unstable_options {
compiler.arg("-Z").arg("unstable-options");
}

for lib_str in &rustdoc_options.lib_strs {
compiler.arg("-L").arg(&lib_str);
}
Expand Down

0 comments on commit 1a732c5

Please sign in to comment.