Skip to content

PathBuf incorrectly transmutes OsString to Vec<u8> #124409

Closed
@RalfJung

Description

PathBuf contains this gem:

rust/library/std/src/path.rs

Lines 1172 to 1175 in f56afa0

#[inline]
fn as_mut_vec(&mut self) -> &mut Vec<u8> {
unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
}

This effectively transmutes an OsString to Vec<u8>. But on Windows, OsString is Wtf8Buf:

/// An owned, growable string of well-formed WTF-8 data.
///
/// Similar to `String`, but can additionally contain surrogate code points
/// if they’re not in a surrogate pair.
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
pub struct Wtf8Buf {
bytes: Vec<u8>,
/// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily
/// know this if we're constructed from a `String` or `&str`.
///
/// It is possible for `bytes` to have valid UTF-8 without this being
/// set, such as when we're concatenating `&Wtf8`'s and surrogates become
/// paired, as we don't bother to rescan the entire string.
is_known_utf8: bool,
}

This is not repr(transparent), so there is no guarantee that we can just transmute this. And I think with layout randomization this can actually fail -- that's probably what happened here.

Is there a reason why this uses transmutes rather than some sort of private accessor that exposes a *mut Vec<u8> through all these layers?

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions