diff --git a/compiler/rustc_driver_impl/src/args.rs b/compiler/rustc_driver_impl/src/args.rs index 42c97cc6a9d74..5ddacc388637b 100644 --- a/compiler/rustc_driver_impl/src/args.rs +++ b/compiler/rustc_driver_impl/src/args.rs @@ -18,6 +18,9 @@ fn arg_expand(arg: String) -> Result, Error> { } } +/// **Note:** This function doesn't interpret argument 0 in any special way. +/// If this function is intended to be used with command line arguments, +/// `argv[0]` must be removed prior to calling it manually. pub fn arg_expand_all(at_args: &[String]) -> Vec { let mut args = Vec::new(); for arg in at_args { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 555917c8b5e9c..88f3b24bc9864 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -237,6 +237,16 @@ fn run_compiler( Box Box + Send>, >, ) -> interface::Result<()> { + // Throw away the first argument, the name of the binary. + // In case of at_args being empty, as might be the case by + // passing empty argument array to execve under some platforms, + // just use an empty slice. + // + // This situation was possible before due to arg_expand_all being + // called before removing the argument, enabling a crash by calling + // the compiler with @empty_file as argv[0] and no more arguments. + let at_args = at_args.get(1..).unwrap_or_default(); + let args = args::arg_expand_all(at_args); let Some(matches) = handle_options(&args) else { return Ok(()) }; @@ -993,9 +1003,6 @@ pub fn print_flag_list( /// So with all that in mind, the comments below have some more detail about the /// contortions done here to get things to work out correctly. pub fn handle_options(args: &[String]) -> Option { - // Throw away the first argument, the name of the binary - let args = &args[1..]; - if args.is_empty() { // user did not write `-v` nor `-Z unstable-options`, so do not // include that extra information. diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 2c514a0c8267b..22356229d0576 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -321,7 +321,6 @@ impl Options { matches: &getopts::Matches, args: Vec, ) -> Result<(Options, RenderOptions), i32> { - let args = &args[1..]; // Check for unstable options. nightly_options::check_nightly_options(matches, &opts()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4fcf0873600ab..da32d429dac17 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -703,13 +703,23 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } fn main_args(at_args: &[String]) -> MainResult { + // Throw away the first argument, the name of the binary. + // In case of at_args being empty, as might be the case by + // passing empty argument array to execve under some platforms, + // just use an empty slice. + // + // This situation was possible before due to arg_expand_all being + // called before removing the argument, enabling a crash by calling + // the compiler with @empty_file as argv[0] and no more arguments. + let at_args = at_args.get(1..).unwrap_or_default(); + let args = rustc_driver::args::arg_expand_all(at_args); let mut options = getopts::Options::new(); for option in opts() { (option.apply)(&mut options); } - let matches = match options.parse(&args[1..]) { + let matches = match options.parse(&args) { Ok(m) => m, Err(err) => { early_error(ErrorOutputType::default(), &err.to_string());