Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc driver: Remove argument 0 before at-expansion to prevent ICE #109084

Merged
merged 1 commit into from
May 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_driver_impl/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ fn arg_expand(arg: String) -> Result<Vec<String>, 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<String> {
let mut args = Vec::new();
for arg in at_args {
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_driver_impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ fn run_compiler(
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + 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(()) };
Expand Down Expand Up @@ -993,9 +1003,6 @@ pub fn print_flag_list<T>(
/// 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<getopts::Matches> {
// 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.
Expand Down
1 change: 0 additions & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,6 @@ impl Options {
matches: &getopts::Matches,
args: Vec<String>,
) -> Result<(Options, RenderOptions), i32> {
let args = &args[1..];
// Check for unstable options.
nightly_options::check_nightly_options(matches, &opts());

Expand Down
12 changes: 11 additions & 1 deletion src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down