Skip to content

Safe Rust code miscompilation due to a bug in LLVM's Global Value Numbering #45839

Description

@RalfJung

lib/src.rs in the foo crate:

#[inline(never)]
pub fn test(gp1: &mut *const i32, gp2: &mut *const i32, b1: bool, b2: bool) -> (i32, i32) {
    let mut g = 0;
    let mut b = 0;
    let y = 6666;
    let mut x = 7777;
    let mut p = &mut g as *const _;

    {
        let mut q = &mut g;
        let mut r = &mut 8888;

        if b1 {
            p = (&y as *const _).wrapping_offset(1);
        }

        if b2 {
            q = &mut x;
        }

        *gp1 = p.wrapping_offset(1234);
        if q as *const _ == p {
            b = 1;
            *gp2 = (q as *const _).wrapping_offset(1234);
            r = q;
        }

        *r = 42;
    }

    return (b, x);
}

src/main.rs in the main crate:

use std::ptr;

extern crate foo;

pub fn main() {
    let mut x1 = ptr::null();
    let mut x2 = ptr::null();
    let mut gp1 = &mut x1;
    let mut gp2 = &mut x2;

    let (b, x) = foo::test(&mut gp1, &mut gp2, true, true);
    println!("b = {}, x = {}", b, x);
}

This prints b = 1, x = 7777. That is wrong; if b is 1, it must be the case that the then-branch in the q as *const _ == p conditional was taken, so r is &mut x (since b2 is true), so x cannot still be 7777.

This is a bug in LLVM's GVN, see https://bugs.llvm.org/show_bug.cgi?id=35229 for the upstream report and some further analysis.

Original C test case by Gil Hur.

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.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions