Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscompilation with enums #121996

Closed
cbeuw opened this issue Mar 4, 2024 · 6 comments · Fixed by #122559
Closed

Miscompilation with enums #121996

cbeuw opened this issue Mar 4, 2024 · 6 comments · Fixed by #122559
Assignees
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@cbeuw
Copy link
Contributor

cbeuw commented Mar 4, 2024

Fuzzer generated custom MIR

#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;

#[custom_mir(dialect = "runtime", phase = "initial")]
fn fn6() {
    mir! {
    let _10: (Adt19,);
    let arr: [u32;8];
    let _23: *mut (Adt19,);
    let _29: i128;
    let _57: (u64, i128, char, isize);
    let _72: isize;
    let _90: Adt19;
    let _91: [char; 2];
    let _92: Adt19;
    let _93: Adt19;
    let _102: ();
    {
    _57 = (0, 0, 'A', 0);
    place!(Field::<(u64, i128, char, isize)>(Variant(_10.0, 3), 1)) = _57;
    _93 = Adt19::Variant3 { fld0: false,fld1: Field::<(u64, i128, char, isize)>(Variant(_10.0, 3), 1),fld2: 0,fld3: 0.,fld4: 0.,fld5: 0,fld6: 0};
    place!(Field::<(u64, i128, char, isize)>(Variant(_93, 3), 1)).2 = 'A';
    _23 = core::ptr::addr_of_mut!(_10);
    _29 = Field::<(u64, i128, char, isize)>(Variant(_93, 3), 1).1;
    _23 = core::ptr::addr_of_mut!(_10);
    place!(Field::<(u64, i128, char, isize)>(Variant(_93, 1), 2)) = (0, 0, 'A', 0);
    place!(Field::<(u64, i128, char, isize)>(Variant(_10.0, 3), 1)) = Field::<(u64, i128, char, isize)>(Variant(_93, 1), 2);
    arr = [0;8];
    _93 = Adt19::Variant2 { fld0: 0,fld1: 0,fld2: 0.,fld3: 0,fld4: arr,fld5: _57 };
    (*_23) = (_93,);
    _92 = _10.0;
    place!(Field::<(u64, i128, char, isize)>(Variant((*_23).0, 2), 5)) = (Field::<(u64, i128, char, isize)>(Variant(_92, 2), 5).0, 0, 'A', 0);
    _72 = Field::<(u64, i128, char, isize)>(Variant(_92, 2), 5).3;
    _90 = Adt19::Variant3 { fld0: false,fld1: Field::<(u64, i128, char, isize)>(Variant(_10.0, 2), 5),fld2: Field::<(u64, i128, char, isize)>(Variant(_10.0, 2), 5).3,fld3: 0.,fld4: 0.,fld5: 0,fld6: 0 };
    _10.0 = Adt19::Variant1 { fld0: 0.,fld1: 0,fld2: Field::<(u64, i128, char, isize)>(Variant(_90, 3), 1),fld3: 0};
    _91 = [Field::<(u64, i128, char, isize)>(Variant((*_23).0, 1), 2).2,'A'];
    Goto(bb53)
    }
    bb53 = {
    Call(_102 = p(_91), ReturnTo(bb56), UnwindUnreachable())
    }
    bb56 = {
    Call(_102 = black_box(Move(_57)), ReturnTo(bb57), UnwindUnreachable())
    }
    bb57 = {
    Return()
    }
    }
}
pub fn main() {
    fn6();
}
#[derive(Debug, Copy, Clone)]
pub enum Adt19 {
    Variant0 {},
    Variant1 {
        fld0: f32,
        fld1: u8,
        fld2: (u64, i128, char, isize),
        fld3: i128,
    },
    Variant2 {
        fld0: u32,
        fld1: u8,
        fld2: f64,
        fld3: u16,
        fld4: [u32; 8],
        fld5: (u64, i128, char, isize),
    },
    Variant3 {
        fld0: bool,
        fld1: (u64, i128, char, isize),
        fld2: isize,
        fld3: f32,
        fld4: f64,
        fld5: usize,
        fld6: i64,
    },
}
fn black_box(x: (u64, i128, char, isize)) {
    core::hint::black_box(x);
}

#[cfg(not(miri))]
fn print_u32(x: u32) {
    extern "C" {
        fn printf(fmt: *const core::ffi::c_char, ...) -> core::ffi::c_int;
    }

    unsafe {
        printf(b"%d\n\0".as_ptr().cast(), x);
    }
}

#[cfg(miri)]
fn print_u32(x: u32) {
    println!("{x}");
}
#[inline(never)]
fn p(x: [char; 2]) {
    print_u32(x[0] as u32)
}

This code has UB under Stacked Borrows, but UB-free under Tree Borrows.

Right:

$ rustc -Zmir-opt-level=0 -Copt-level=0 3440904-debug.rs && ./3440904-debug 
65

Wrong:

$ rustc -Zmir-opt-level=0 -Copt-level=1 3440904-debug.rs && ./3440904-debug 
0

While it looks like an LLVM issue, I couldn't get an IR-only reproduction. It's possible that rustc is producing IR with UBs

On latest nightly

rustc 1.78.0-nightly (516b6162a 2024-03-03)
binary: rustc
commit-hash: 516b6162a2ea8e66678c09e8243ebd83e4b8eeea
commit-date: 2024-03-03
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0

cc @RalfJung

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Mar 4, 2024
@jieyouxu jieyouxu added the A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html label Mar 4, 2024
@workingjubilee workingjubilee added A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Mar 5, 2024
@workingjubilee
Copy link
Member

I am only refraining from adding I-unsound so far because there's no surface Rust repro yet.

@workingjubilee workingjubilee added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 5, 2024
@DianQK
Copy link
Member

DianQK commented Mar 5, 2024

Perhaps EarlyCSEPass? We should get 279172874305, but we get 279172874240.

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

@DianQK
Copy link
Member

DianQK commented Mar 5, 2024

@DianQK
Copy link
Member

DianQK commented Mar 5, 2024

Upstream issue: llvm/llvm-project#84025

@saethlin saethlin added the I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness label Mar 5, 2024
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Mar 5, 2024
@saethlin
Copy link
Member

saethlin commented Mar 5, 2024

I am only refraining from adding I-unsound so far because there's no surface Rust repro yet.

I do not have such qualms, especially because a fix is already on the way.

@nikic nikic added the llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes label Mar 6, 2024
@apiraino
Copy link
Contributor

apiraino commented Mar 6, 2024

WG-prioritization assigning priority (Zulip discussion).

Keeping an eye on this issue to evaluate what to do when the LLVM fix lands

@rustbot label -I-prioritize +P-high

@rustbot rustbot added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Mar 6, 2024
@bors bors closed this as completed in 7aa1de7 Mar 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-MIR Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.html C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness llvm-fixed-upstream Issue expected to be fixed by the next major LLVM upgrade, or backported fixes P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants