Skip to content

Public API “shape_slice” “shape_vec” “shape_vec_u8” constructs unaligned references causing Undefined Behavior #352

@lwz23

Description

@lwz23

Hello,
We are working on a static analysis tool designed to detect unsoundness and safety violations in Rust projects. We identified a soundness issue in tensorbase/crates/base/src/mem.rs.

pub fn shape_slice<T>(slice: &[u8]) -> &[T] {

pub fn shape_vec<T>(v: Vec<u8>) -> Vec<T> {

pub fn shape_vec_u8<T>(v: Vec<T>) -> Vec<u8> {

Location:
The vulnerability is located in the public function shape_slice:

pub fn shape_slice<T>(slice: &[u8]) -> &[T] {
    unsafe {
        std::slice::from_raw_parts(
            slice.as_ptr() as *const T,
            slice.len() / mem::size_of::<T>(),
        )
    }
}

This function is pub and located in a pub mod, making it accessible to external users.
Description:
The function casts a byte slice &[u8] (which has an alignment of 1) to a slice of generic type &[T]. However, it does not check if the input slice.as_ptr() satisfies the alignment requirements of T.
According to the safety contract of std::slice::from_raw_parts:
The pointer must be properly aligned.
If a user passes a byte slice that is not aligned to std::mem::align_of::(), creating the returned slice &[T] is immediate Undefined Behavior (UB), even if the data is never read.

Proof of Concept (PoC):
We constructed a PoC where we pass a misaligned byte slice (offset by 1 byte) and attempt to view it as &[u32] (which requires 4-byte alignment).

use std::mem;
use std::slice;

// The vulnerable function from tensorbase/crates/base/src/mem.rs
pub fn shape_slice<T>(slice: &[u8]) -> &[T] {
    unsafe {
        slice::from_raw_parts(
            slice.as_ptr() as *const T,
            slice.len() / mem::size_of::<T>(),
        )
    }
}

fn main() {
    // 1. Create a byte array
    let bytes: [u8; 16] = [0; 16];

    // 2. Create a "misaligned" sub-slice.
    // bytes[0] is aligned (stack allocation), so bytes[1] is definitely 
    // NOT aligned for u32 (which requires 4-byte alignment).
    let misaligned_slice = &bytes[1..];

    // 3. Trigger UB
    // This attempts to create &[u32] at an address like 0x...01
    println!("Attempting to create misaligned slice...");
    let _u32_slice: &[u32] = shape_slice(misaligned_slice);
    
    println!("If you see this without Miri, UB has occurred silently.");
}

Miri Output:
Running the PoC with Miri (cargo miri run) confirms the issue:

error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
   --> .../slice/raw.rs:138:9
    |
138 |         &*ptr::slice_from_raw_parts(data, len)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)

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