Skip to content

Pointer dereferenced after allocation was freed in String::replace_range #2759

Closed
rust-lang/rust
#106950
@Erutuon

Description

@Erutuon

Miri reported a pointer being dereferenced after its allocation was freed in a function using String::replace_range in a test (ip::sanitize_ip_recognizes_subpages_of_ipv6_address) in the mwtitle library, and this was reported in Wikimedia Phabricator by @legoktm.

I couldn't detect an error in the code, and the test runs fine in stable and nightly, but I reduced the Miri-error-producing code to this minimal example:

fn main() {
    let mut input = "1".to_string();
    input.replace_range(0..0, "0");
}

If I reduce the input "1" or the replacement "0" to a zero-length string, or if I change the range to 0.. or .., there is no error.

The code looks correct and it compiles and runs fine in nightly. I thought this might be a Rustc problem generating code that's incorrect (freeing an allocation early) but happens not to crash so is only caught by Miri, but I'm not very familiar with how Miri works, so I thought I'd post here first.

The full error from `cargo +nightly miri run`

Preparing a sysroot for Miri (target: x86_64-unknown-linux-gnu)... done
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner target/miri/x86_64-unknown-linux-gnu/debug/miri-mwtitle`
error: Undefined Behavior: pointer to alloc1704 was dereferenced after this allocation got freed
   --> ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter.rs:127:1
    |
127 | / iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, {
128 | |     fn is_sorted_by(self, mut compare: F) -> bool
129 | |     where
130 | |         Self: Sized,
...   |
136 | |     }
137 | | }}
    | |__^ pointer to alloc1704 was dereferenced after this allocation got freed
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside ` as std::iter::ExactSizeIterator>::len` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:25:22: 25:55
    = note: inside ` as std::ops::Drop>::drop` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/vec/drain.rs:201:24: 201:34
    = note: inside `std::ptr::drop_in_place::> - shim(Some(std::vec::Drain<'_, u8>))` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:490:1: 490:56
    = note: inside `std::ptr::drop_in_place::>> - shim(Some(std::vec::Splice<'_, std::str::Bytes<'_>>))` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:490:1: 490:56
    = note: inside `std::string::String::replace_range::>` at ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/string.rs:1826:80: 1826:81
note: inside `main`
   --> src/main.rs:3:5
    |
3   |     input.replace_range(0..0, "0");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `len` which comes from the expansion of the macro `iterator` (in Nightly builds, run with -Z macro-backtrace for more info)

note: some details are omitted, run with MIRIFLAGS=-Zmiri-backtrace=full for a verbose backtrace

error: aborting due to previous error

Versions

Probably doesn't matter, but I ran this in Ubuntu in WSL.

rustc +nightly --version --verbose && echo && cargo +nightly miri --version:

rustc 1.68.0-nightly (9e75dddf6 2023-01-15)
binary: rustc
commit-hash: 9e75dddf609c0201d03f9792e850f95d6a283d11
commit-date: 2023-01-15
host: x86_64-unknown-linux-gnu
release: 1.68.0-nightly
LLVM version: 15.0.6

miri 0.1.0 (9e75ddd 2023-01-15)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions