diff --git a/src/ini.rs b/src/ini.rs index f1cf0da..748d1b1 100644 --- a/src/ini.rs +++ b/src/ini.rs @@ -1017,7 +1017,13 @@ impl Ini { current_key = Some(key.clone()); } - let value = trimmed[delimiter + 1..].trim().to_owned(); + // `delimiter` is a byte offset and may itself be multi-byte, so advance by + // its UTF-8 length. + let delimiter_len = trimmed[delimiter..] + .chars() + .next() + .map_or(1, char::len_utf8); + let value = trimmed[delimiter + delimiter_len..].trim().to_owned(); valmap.insert(key, Some(value)); } diff --git a/tests/test.rs b/tests/test.rs index 6807c52..c8ce8bf 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -973,3 +973,18 @@ fn serde_case_sensitive_roundtrip() -> Result<(), Box> { Ok(()) } + +#[test] +fn multibyte_delimiter_does_not_panic() -> Result<(), Box> { + use configparser::ini::IniDefault; + + // A multi-byte delimiter must not split on a non-char boundary. + let mut defaults = IniDefault::default(); + defaults.delimiters = vec!['\u{00a7}']; // section sign, 2 bytes in UTF-8 + + let mut config = Ini::new_from_defaults(defaults); + config.read(String::from("[s]\nkey\u{00a7}value\n"))?; + + assert_eq!(config.get("s", "key"), Some(String::from("value"))); + Ok(()) +}