Skip to content

Lint against String::from_raw_parts #14293

Open
@robertbastian

Description

@robertbastian

What it does

Lints against usages of String::from_raw_parts. This should be done in two steps, Vec::from_raw_parts and String::from_utf8_unchecked.

rust-lang/rust#136775 updated String::from_raw_parts's docs to delegate the safety requirements to Vec::from_raw_parts's and String::from_utf8_unchecked's docs anyway.

Advantage

  • String::from_raw_parts has conflated safety requirements that should be justified in two steps:
    • Vec::from_raw_parts has complicated language-level safety requirements that have to be manually justified and are insta-UB (?) if violated
    • String::from_utf8_unchecked has a relatively trivial library-level safety requirement, that could be checked by using String::from_utf8 instead

Drawbacks

No response

Example

// SAFETY: 
// * `ptr` was allocated using the global allocator
// * `T` (= `u8`) has the same alignment as what `ptr` was allocated with
// * The size of T (= u8) times the capacity is the same size as `ptr` was allocated with
// * `len` is use for both `len` and `capacity`
// * The first `len` values are properly initialized values of type `T` (= `u8`).
// * `capacity` (= `len`) is the capacity that `ptr` was allocated with.
// * The allocated size in bytes is no larger than `isize::MAX`
// * The bytes contain valid UTF-8
let string = unsafe { String::from_raw_parts(pointer, len) };

Could be written as:

// SAFETY: 
// * `ptr` was allocated using the global allocator
// * `T` (= `u8`) has the same alignment as what `ptr` was allocated with
// * The size of T (= u8) times the capacity is the same size as `ptr` was allocated with
// * `len` is use for both `len` and `capacity`
// * The first `len` values are properly initialized values of type `T` (= `u8`).
// * `capacity` (= `len`) is the capacity that `ptr` was allocated with.
// * The allocated size in bytes is no larger than `isize::MAX`
let bytes = unsafe { Vec::from_raw_parts(ptr, len, len) };
// SAFETY: 
// * The bytes contain valid UTF-8
let string = unsafe { String::from_utf8_unchecked(bytes) };

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lints

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions