Skip to content

Add support for empty init arguments in the command line parser #176

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
61 changes: 43 additions & 18 deletions src/cmdline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,30 +473,45 @@ impl Cmdline {

// Check first occurrence of the INIT_ARGS_SEPARATOR that is not between double quotes.
// All chars following the INIT_ARGS_SEPARATOR will be parsed as init args.
let (mut boot_args, mut init_args) = match cmdline_raw
.match_indices(INIT_ARGS_SEPARATOR)
.find(|&separator_occurrence| {
Self::check_outside_double_quotes(&cmdline_raw[..(separator_occurrence.0)])
}) {
None => (cmdline_raw, ""),
Some((delimiter_index, _)) => (
&cmdline_raw[..delimiter_index],
// This does not overflow as long as `delimiter_index + INIT_ARGS_SEPARATOR.len()`
// is pointing to the first char after the INIT_ARGS_SEPARATOR which always exists;
// as a result, `delimiter_index + INIT_ARGS_SEPARATOR.len()` is less or equal to the
// length of the initial string.
&cmdline_raw[(delimiter_index + INIT_ARGS_SEPARATOR.len())..],
),
};
let delimiter_needle = INIT_ARGS_SEPARATOR.trim_end();
let (mut boot_args, init_args) =
match cmdline_raw
.match_indices(delimiter_needle)
.find_map(|(idx, occur)| {
let mut trailing_chars = 0;

// If something is after the seperator then it also has to be an ASCII space
let succ = &cmdline_raw[(idx + occur.len())..];
if !succ.is_empty() {
if succ.starts_with(' ') {
// Include the space character into the further process
trailing_chars += 1;
} else {
return None;
}
}

if !Self::check_outside_double_quotes(&cmdline_raw[..idx]) {
return None;
}
Some((idx, delimiter_needle.len() + trailing_chars))
}) {
None => (cmdline_raw, None),
Some((delimiter_index, delimiter_len)) => (
&cmdline_raw[..delimiter_index],
// The index operation does not go out of bounds because the result of
// match_indices+find_map at most points to the end of the string.
Some(cmdline_raw[(delimiter_index + delimiter_len)..].trim()),
),
};

boot_args = boot_args.trim();
init_args = init_args.trim();

// Step 2: Check if capacity provided for the cmdline is not exceeded and create a new `Cmdline`
// if size check passes.
let mut cmdline_size = boot_args.len().checked_add(1).ok_or(Error::TooLarge)?;

if !init_args.is_empty() {
if let Some(init_args) = init_args {
cmdline_size = cmdline_size
.checked_add(INIT_ARGS_SEPARATOR.len())
.ok_or(Error::TooLarge)?;
Expand All @@ -512,7 +527,7 @@ impl Cmdline {

Ok(Cmdline {
boot_args: boot_args.to_string(),
init_args: init_args.to_string(),
init_args: init_args.unwrap_or("").to_string(),
capacity,
})
}
Expand Down Expand Up @@ -817,6 +832,16 @@ mod tests {

assert_eq!(cl.boot_args, "foo=\"bar--baz\" foo");
assert_eq!(cl.init_args, "");

let cl = Cmdline::try_from("--foo --bar -- ", CMDLINE_MAX_SIZE).unwrap();

assert_eq!(cl.boot_args, "--foo --bar");
assert_eq!(cl.init_args, "");

let cl = Cmdline::try_from("--foo --bar --", CMDLINE_MAX_SIZE).unwrap();

assert_eq!(cl.boot_args, "--foo --bar");
assert_eq!(cl.init_args, "");
}

#[test]
Expand Down