Merge pull request #86 from dasJ/fix/osrelease-parser

Make the os-release parser more precise
This commit is contained in:
nikstur 2023-01-30 15:57:12 +01:00 committed by GitHub
commit 60e28106e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 46 additions and 4 deletions

View File

@ -46,17 +46,31 @@ impl OsRelease {
pub fn from_str(value: &str) -> Result<Self> { pub fn from_str(value: &str) -> Result<Self> {
let mut map = BTreeMap::new(); let mut map = BTreeMap::new();
let key_value_lines = value.lines().map(|x| x.split('=').collect::<Vec<&str>>()); // All valid lines
let lines = value
.lines()
.map(str::trim)
.filter(|x| !x.starts_with('#') && !x.is_empty());
// Split into keys/values
let key_value_lines = lines.map(|x| x.split('=').collect::<Vec<&str>>());
for kv in key_value_lines { for kv in key_value_lines {
let k = kv let k = kv
.first() .first()
.with_context(|| format!("Failed to get first element from {kv:?}"))?; .with_context(|| format!("Failed to get first element from {kv:?}"))?;
let v = kv let v = kv
.get(1) .get(1)
.map(|s| s.trim_matches('"')) .map(|s| s.strip_prefix(|c| c == '"' || c == '\'').unwrap_or(s))
.map(|s| s.strip_suffix(|c| c == '"' || c == '\'').unwrap_or(s))
.with_context(|| format!("Failed to get second element from {kv:?}"))?; .with_context(|| format!("Failed to get second element from {kv:?}"))?;
map.insert(String::from(*k), v.into()); // Clean up the value. We already have the value without leading/tailing "
// so we just need to unescape the string.
let v = v
.replace("\\$", "$")
.replace("\\\"", "\"")
.replace("\\`", "`")
.replace("\\\\", "\\");
map.insert(String::from(*k), v);
} }
Ok(Self(map)) Ok(Self(map))
@ -89,4 +103,32 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
fn escaping_works() -> Result<()> {
let teststring = r#"
NO_QUOTES=systemd-boot
DOUBLE_QUOTES="systemd-boot"
SINGLE_QUOTES='systemd-boot'
UNESCAPED_DOLLAR=$1.2
ESCAPED_DOLLAR=\$1.2
UNESCAPED_BACKTICK=`1.2
ESCAPED_BACKTICK=\`1.2
UNESCAPED_QUOTE=""1.2"
ESCAPED_QUOTE=\"1.2
"#;
let os_release = OsRelease::from_str(teststring)?;
assert!(os_release.0["NO_QUOTES"] == "systemd-boot");
assert!(os_release.0["DOUBLE_QUOTES"] == "systemd-boot");
assert!(os_release.0["SINGLE_QUOTES"] == "systemd-boot");
assert!(os_release.0["UNESCAPED_DOLLAR"] == "$1.2");
assert!(os_release.0["ESCAPED_DOLLAR"] == "$1.2");
assert!(os_release.0["UNESCAPED_BACKTICK"] == "`1.2");
assert!(os_release.0["ESCAPED_BACKTICK"] == "`1.2");
assert!(os_release.0["UNESCAPED_QUOTE"] == "\"1.2");
assert!(os_release.0["ESCAPED_QUOTE"] == "\"1.2");
Ok(())
}
} }