Closed
Description
It's possible to use String::replace_range
to create invalid strings containing broken Unicode. This happens because replace_range
checks range bounds twice - first time to check parameter validity and second time for actually doing the splice.
use std::cell::Cell;
use std::ops::{Bound, RangeBounds};
use std::str;
struct EvilRange(Cell<bool>);
impl RangeBounds<usize> for EvilRange {
fn start_bound(&self) -> Bound<&usize> {
Bound::Included(if self.0.get() {
&1
} else {
self.0.set(true);
&0
})
}
fn end_bound(&self) -> Bound<&usize> {
Bound::Unbounded
}
}
fn main() {
let mut s = String::from("🦀");
s.replace_range(EvilRange(Cell::new(false)), "");
println!("{:?}", str::from_utf8(s.as_bytes()));
}
This will print Utf8Error
showing that a string is not valid UTF-8.