Skip to content

Miscompile from LLVM assuming that globals don't get merged #162078

Description

@maxdexh

This issue is the exact inverse of #161973. Instead of compiling code that assumes things living at the same address have the same contents (which there is no guarantee for), this issue demonstrates the optimizer making that assumption instead.

As such, the code below is obviously sound (the unsafe is only to get it to weaponize the already UB noundef undef). It outputs (modulo exact address)

thread 'main' (1) panicked at /app/example.rs:6:5:
assertion `left == right` failed
  left: 106946049351680
 right: 106946049351680

https://godbolt.org/z/z5redezGj

use std::mem::MaybeUninit;

fn get_first_if_half(p: &[u32]) -> u32 {
    let half = const { &[MaybeUninit::uninit(), MaybeUninit::new(0)] };
    
    // Simply observe that the addresses are equal, without making
    // assumptions about what that implies
    assert_eq!(p.as_ptr().addr(), half.as_ptr().addr());

    // LLVM will happily use that to inline the `undef` from `half` here.
    // But uninit globals can get merged into init globals by the linker!
    p[0]
}

pub fn main() {
    // Linker will merge this with `half` from the other function
    let full = std::hint::black_box(const { &[0, 0] });

    // Below is just exploitation to make it miscompile. 
    // LLVM is returning `undef` for the `u32`, which is already UB

    if get_first_if_half(full) != get_first_if_half(full) {
        // SAFETY: We loaded the first item in `full` twice; 
        // 0 != 0 is impossible.
        unsafe { std::hint::unreachable_unchecked() }
    }
}

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-linkersArea: linkers... you gotta love linkersC-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-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem teamneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions