Skip to content

slice::element_offset can produce false positives via current operational semantics #161376

Description

@Plecra

As of #126770

let self_start = self.as_ptr() as usize;
let elem_start = element as *const T as usize;
let byte_offset = elem_start.wrapping_sub(self_start);
if byte_offset % mem::size_of::<T>() != 0 {
return None;
}
let offset = byte_offset / mem::size_of::<T>();
if offset < self.len() { Some(offset) } else { None }

the element_offset method is implemented by comparing the addresses of two pointers. For elements within the same allocation, this has the correct behaviour, however address equality and ordering between independent allocations have no guarantees via LLVM and I expect the intended rust opsem. For example, we want to be able to alias immutable allocations with the same data, and we want to be able to elide mallocs that are detected to not escape a scope, and the compiler invents addresses for the objects in that malloc: This is capable of producing pointers to independent live allocations with the same address.

With pointer comparison defined to ignore provenance, it cannot observe this distinction so can give a false positive, identifying an arbitrary element in a slice as having the "same address" as a pointer in a different allocation.

An example of a false positive would be

fn foo(x: &[u32]) -> &u32 {
    assert!(x.len() > 0);
    x.element_offset(&10).unwrap()
}
// it is legitimate to transform this into 
fn foo(x: &[u32]) -> &u32 {
    assert!(x.len() > 0);
    // decide that the address of the temporary is == x.as_ptr().addr(), and simplify
    &x[0]
}

(edit for clarification: I'm not aware of rust's semantics here, I just know that in the past llvm has had independent allocations be incomparable in this way, and while talking with nia we found a series of examples of llvm treating them as such)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-raw-pointersArea: raw pointers, MaybeUninit, NonNullC-bugCategory: This is a bug.I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}T-langRelevant to the language teamT-libsRelevant to the library team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions