Skip to content

LLVM replaces pointer with null without respecting provenance #163541

Description

@maxdexh

Based on an observation by @scottmcm on zulip.

https://rust.godbolt.org/z/z6Evsrdob

pub fn wat(p: *const u8) -> *const u8 {
    assert!(p.is_null());
    p // optimized to `ptr null`, without provenance
}

pub fn off_and_back(p: *const u8, n: usize) -> *const u8 {
    let q = p.wrapping_add(n); // q = p + n
    assert!(q.is_null(), "{q:?} is not null");
    wat(q).wrapping_sub(n) // q - n = p
}

pub fn broken(x: &u8) -> u8 {
    // SAFETY: `off_and_back` returns `x`, which is valid for reads
    unsafe {
        off_and_back(x, std::ptr::from_ref(x).addr().wrapping_neg())
            .read()
    }
}


pub fn main() {
    // panics on "0x0 is not null"
    broken(std::hint::black_box(&1));
}

Similar issue: #80309

@rustbot label I-miscompile A-llvm I-unsound T-compiler

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-lowLow priorityT-compilerRelevant to the compiler 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