mirror of
https://github.com/containers/bootc.git
synced 2026-02-05 15:45:53 +01:00
kernel_cmdline: Fix parsing/equivalence of "outside" quoted args
Primary motivation here is that these two should be equivalent: foo="quoted value" "foo=quoted value" This also adds tests for a few more oddball cases that weren't covered before but clarify the expected kernel behavior. Closes: #1737 Signed-off-by: John Eckersberg <jeckersb@redhat.com>
This commit is contained in:
committed by
Colin Walters
parent
3181bb58e7
commit
87bcbd9ae9
@@ -421,27 +421,31 @@ impl<'a> Parameter<'a> {
|
||||
/// This is an internal method that assumes the input has already been
|
||||
/// split into a single parameter (e.g., by CmdlineIterBytes).
|
||||
fn parse_internal(input: &'a [u8]) -> Option<Self> {
|
||||
let equals = input.iter().position(|b| *b == b'=');
|
||||
// *Only* the first and last double quotes are stripped
|
||||
let dequoted_input = input.strip_prefix(b"\"").unwrap_or(input);
|
||||
let dequoted_input = dequoted_input.strip_suffix(b"\"").unwrap_or(dequoted_input);
|
||||
|
||||
let equals = dequoted_input.iter().position(|b| *b == b'=');
|
||||
|
||||
match equals {
|
||||
None => Some(Self {
|
||||
parameter: input,
|
||||
key: ParameterKey(input),
|
||||
key: ParameterKey(dequoted_input),
|
||||
value: None,
|
||||
}),
|
||||
Some(i) => {
|
||||
let (key, mut value) = input.split_at(i);
|
||||
let (key, mut value) = dequoted_input.split_at(i);
|
||||
let key = ParameterKey(key);
|
||||
|
||||
// skip `=`, we know it's the first byte because we
|
||||
// found it above
|
||||
value = &value[1..];
|
||||
|
||||
// *Only* the first and last double quotes are stripped
|
||||
value = {
|
||||
let v = value.strip_prefix(b"\"").unwrap_or(value);
|
||||
v.strip_suffix(b"\"").unwrap_or(v)
|
||||
};
|
||||
// If there is a quote after the equals, skip it. If
|
||||
// there was a closing quote at the end of the value,
|
||||
// we would have already removed it in
|
||||
// `dequoted_input` above
|
||||
value = value.strip_prefix(b"\"").unwrap_or(value);
|
||||
|
||||
Some(Self {
|
||||
parameter: input,
|
||||
@@ -528,6 +532,10 @@ mod tests {
|
||||
|
||||
let p = param("foo=trailing_quotes\"");
|
||||
assert_eq!(p.value, Some(b"trailing_quotes".as_slice()));
|
||||
|
||||
let outside_quoted = param("\"foo=quoted value\"");
|
||||
let value_quoted = param("foo=\"quoted value\"");
|
||||
assert_eq!(outside_quoted, value_quoted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -549,9 +557,22 @@ mod tests {
|
||||
fn test_parameter_pathological() {
|
||||
// valid things that certified insane people would do
|
||||
|
||||
// quotes don't get removed from keys
|
||||
let p = param("\"\"\"");
|
||||
assert_eq!(p.key.0, b"\"\"\"");
|
||||
// you can quote just the key part in a key-value param, but
|
||||
// the end quote is actually part of the key as far as the
|
||||
// kernel is concerned...
|
||||
let p = param("\"foo\"=bar");
|
||||
assert_eq!(p.key.0, b"foo\"");
|
||||
assert_eq!(p.value, Some(b"bar".as_slice()));
|
||||
// and it is definitely not equal to an unquoted foo ...
|
||||
assert_ne!(p, param("foo=bar"));
|
||||
|
||||
// ... but if you close the quote immediately after the
|
||||
// equals sign, it does get removed.
|
||||
let p = param("\"foo=\"bar");
|
||||
assert_eq!(p.key.0, b"foo");
|
||||
assert_eq!(p.value, Some(b"bar".as_slice()));
|
||||
// ... so of course this makes sense ...
|
||||
assert_eq!(p, param("foo=bar"));
|
||||
|
||||
// quotes only get stripped from the absolute ends of values
|
||||
let p = param("foo=\"internal\"quotes\"are\"ok\"");
|
||||
|
||||
@@ -426,6 +426,16 @@ mod tests {
|
||||
fn test_parameter_quoted() {
|
||||
let p = param("foo=\"quoted value\"");
|
||||
assert_eq!(p.value(), Some("quoted value"));
|
||||
|
||||
let p = param("foo=\"unclosed quotes");
|
||||
assert_eq!(p.value(), Some("unclosed quotes"));
|
||||
|
||||
let p = param("foo=trailing_quotes\"");
|
||||
assert_eq!(p.value(), Some("trailing_quotes"));
|
||||
|
||||
let outside_quoted = param("\"foo=quoted value\"");
|
||||
let value_quoted = param("foo=\"quoted value\"");
|
||||
assert_eq!(outside_quoted, value_quoted);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -447,9 +457,22 @@ mod tests {
|
||||
fn test_parameter_pathological() {
|
||||
// valid things that certified insane people would do
|
||||
|
||||
// quotes don't get removed from keys
|
||||
let p = param("\"\"\"");
|
||||
assert_eq!(p.key(), "\"\"\"".into());
|
||||
// you can quote just the key part in a key-value param, but
|
||||
// the end quote is actually part of the key as far as the
|
||||
// kernel is concerned...
|
||||
let p = param("\"foo\"=bar");
|
||||
assert_eq!(p.key(), ParameterKey::from("foo\""));
|
||||
assert_eq!(p.value(), Some("bar"));
|
||||
// and it is definitely not equal to an unquoted foo ...
|
||||
assert_ne!(p, param("foo=bar"));
|
||||
|
||||
// ... but if you close the quote immediately after the
|
||||
// equals sign, it does get removed.
|
||||
let p = param("\"foo=\"bar");
|
||||
assert_eq!(p.key(), ParameterKey::from("foo"));
|
||||
assert_eq!(p.value(), Some("bar"));
|
||||
// ... so of course this makes sense ...
|
||||
assert_eq!(p, param("foo=bar"));
|
||||
|
||||
// quotes only get stripped from the absolute ends of values
|
||||
let p = param("foo=\"internal\"quotes\"are\"ok\"");
|
||||
|
||||
Reference in New Issue
Block a user