diff --git a/src/uu/stty/src/stty.rs b/src/uu/stty/src/stty.rs index dc1019ce1ab..db922e82f61 100644 --- a/src/uu/stty/src/stty.rs +++ b/src/uu/stty/src/stty.rs @@ -532,9 +532,15 @@ fn parse_saved_state(arg: &str) -> Option> { // Validate all parts are non-empty valid hex let mut values = Vec::with_capacity(expected_parts); for (i, part) in parts.iter().enumerate() { + // `from_str_radix` doesn't document its behavior for this case, + // thus, we do this to guarantee stability if part.is_empty() { return None; // GNU rejects empty hex values } + // TO-DO: avoid `from_str_radix` + if part.as_bytes()[0] == b'+' { + return None; + } let val = u32::from_str_radix(part, 16).ok()?; // Control characters (indices 4+) must fit in u8 @@ -1430,6 +1436,24 @@ mod tests { assert_eq!(parse_rows_cols("65537"), Some(1)); // wraps to 1 } + #[test] + fn test_sane_parse_saved_state() { + let expected_parts = 4 + nix::libc::NCCS; + let mut parts: Vec = ["00", "01", "ff", "7f"].map(str::to_string).into(); + parts.resize(expected_parts, "00".to_string()); + let input = parts.join(":"); + assert!(parse_saved_state(&input).is_some()); + } + + #[test] + fn test_parse_saved_state_no_plus() { + let expected_parts = 4 + nix::libc::NCCS; + let mut parts: Vec = ["+00", "00", "00", "00"].map(str::to_string).into(); + parts.resize(expected_parts, "00".to_string()); + let input = parts.join(":"); + assert_eq!(parse_saved_state(&input), None); + } + // Sane control character defaults #[test] fn test_get_sane_control_char_values() {