Skip to content

String::as_mut_ptr is invalidated in unexected ways #158166

Description

@RalfJung

This code has UB under both Stacked and Tree Borrows:

fn main() {
    let mut s = String::with_capacity(10);
    s.push('x');
    let ptr = s.as_mut_ptr();
    unsafe { ptr.write(0x20) };
    let _ptr2 = s.as_mut_ptr(); // creates a slice that aliases with `ptr`.
    // That is considered like a read access, and since `ptr` is derived from
    // a mutable reference such a foreign read access invalidates `ptr`.
    unsafe { ptr.write(97) }; // UB
    println!("{s:?}");
}

The corresponding code with Vec is fine, because Vec::as_mut_ptr avoids invalidating previously created raw pointers to the vec's contents. String::as_mut_ptr does not exist, the code above relies on DerefMut for String and str::as_mut_ptr, which creates some extra references that cause unexpected invalidation.

Cc @rust-lang/libs-api -- would you be open to the idea of having as_mut_ptr on String as well?

Also see #97483, #106593

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-collectionsArea: `std::collections`A-raw-pointersArea: raw pointers, MaybeUninit, NonNullA-strArea: str and StringC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem team

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions