Skip to content

New lint: unnecessary use of std::ptr::read_unaligned() with slices #4891

Open
@Shnatsel

Description

@Shnatsel

During safety-dance audit I've encountered the following unsafe code pattern that can be converted to safe code:

fn read_u32(bytes: &[u8]) -> u32 {
    assert!(bytes.len() >= 4); // bounds check
    unsafe { ptr::read_unaligned(*bytes as *const u32)}
}

This is common in binary format decoders that need to take a chunk of byte stream and interpret it as a value. The exact target value may vary - it can be any primitive numerical type.

Ever since TryInto got stabilized this can be rewritten in safe code with identical performance, although the safe solution is not really obvious:

fn read_u32(bytes: &[u8]) -> u32 {
    // try_into() cannot fail because slice len is always 4
    let bytes_to_convert: [u8; 4] = bytes[..4].try_into().unwrap();
    u32::from_ne_bytes(bytes_to_convert)
}

This may look like it does a lot of more and would be slower, but rustc produces identical code for both versions.

If converting to f32 or f64, the last line would instead be the following: f32::from_bits(u32::from_ne_bytes(bytes_to_convert))

See from_bits() documentation for more info on converting bytes to floats.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lintArea: New lintsE-mediumCall for participation: Medium difficulty level problem and requires some initial experience.L-styleLint: Belongs in the style lint groupT-middleType: Probably requires verifiying types

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions