-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-raw-pointersArea: raw pointers, MaybeUninit, NonNullArea: raw pointers, MaybeUninit, NonNullA-rustlantisA miscompilation found by RustlantisA miscompilation found by RustlantisI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
Description
Again, fuzzer generated code and minimised to surface Rust. Miri reports no UB under either aliasing model.
extern crate core;
use core::ptr;
pub fn dump_var(val0: u16) {
println!("{val0}");
}
// extern "C" {
// fn dump_var(x: u16);
// }
// #[no_mangle]
pub unsafe fn fn10_rs() -> *const *mut i64 {
let mut _16: usize = 0;
let mut _23: i128 = 0;
let mut isize_min: isize = 0;
let mut _46: i64 = 0;
let mut _107: i16 = 0;
let mut _47: u16 = 0;
let mut _88: usize = 0;
let mut _31: *mut u8 = ptr::null_mut();
let mut _33: *mut *mut i64 = ptr::null_mut();
let mut _81: *const i128 = ptr::null();
let mut _90: *mut u8 = ptr::null_mut();
let mut _177: *mut i64 = ptr::null_mut();
let mut _44: ((u64, u64, u8), u32, f32) = Default::default();
let mut _61: ((u64, u64, u8), u32, f32) = Default::default();
let mut tup: (((u64, u64, u8), u32, f32), bool) = Default::default();
let mut _95: (((u64, u64, u8), u32, f32), bool) = Default::default();
'bb2: loop {
let two: u16 = 2;
_44.0 .2 = 1;
_31 = core::ptr::addr_of_mut!(_44.0 .2);
_23 = 11;
'bb45: loop {
(*_31) = 1;
isize_min = isize::MIN;
'bb65: loop {
let tup_ptr = core::ptr::addr_of_mut!(tup);
_31 = core::ptr::addr_of_mut!((*tup_ptr).0 .0 .2);
_16 = 18215089233857363959_usize;
match isize_min {
isize::MIN => {
_90 = _31.wrapping_offset(isize::MIN);
_95.0 = _44;
_46 = 42;
_81 = core::ptr::addr_of!(_23);
_44 = tup.0;
_88 = _16;
'bb80: loop {
_31 = _90.wrapping_offset(isize_min);
match *_81 {
11 => 'bb88: loop {
let tup_ptr2 = core::ptr::addr_of_mut!(tup);
(*tup_ptr2) = _95;
isize_min = _107 as isize;
_47 = two >> *_31;
(*tup_ptr) = _95;
match _88 {
18215089233857363959 => {
*_31 = _61.0 .2.swap_bytes();
_88 = (*tup_ptr2).0 .2 as usize;
_33 = core::ptr::addr_of_mut!(_177);
match _46 {
42 => {
(*_33) = core::ptr::addr_of_mut!(_46);
match *_177 {
42 => {
dump_var(_47);
return core::ptr::addr_of!(_177);
}
_ => continue 'bb2,
}
}
_ => match *_81 {
11 => continue 'bb88,
_ => continue 'bb65,
},
}
}
0 => continue 'bb80,
_ => continue 'bb65,
}
},
_ => continue 'bb65,
}
}
}
_ => continue 'bb45,
}
}
}
}
}
pub fn main() {
unsafe {
fn10_rs();
}
}
The correct output is 1, evaluated from two >> *_31
where _31
points to 1 after having been roundtripped with two .wrapping_offset(isize::MIN)
.
It outputs 2 with -Copt-level >= 1
.
% rustc -Copt-level=0 repro.rs && ./repro
1
% rustc -Copt-level=1 repro.rs && ./repro
2
Not sure if rustc is emitting LLVM IR with UB or it's a bug in LLVM. llvm-reduce
gave me this which calls dump_var(2)
with opt -O1
: https://godbolt.org/z/q6GWPq9qs, but the GEP indices don't look right.
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-macosx11.0.0"
define ptr @fn10_rs() {
start:
%_17 = alloca { { { i64, i64, i8, [7 x i8] }, i32, float }, i8, [7 x i8] }, align 8
%tup = alloca { { { i64, i64, i8, [7 x i8] }, i32, float }, i8, [7 x i8] }, align 8
%0 = getelementptr { i64, i64, i8, [7 x i8] }, ptr %tup, i64 -384307168202282325, i32 1
%1 = getelementptr i8, ptr %0, i64 -9223372036854775808
call void @llvm.memcpy.p0.p0.i64(ptr %tup, ptr %_17, i64 40, i1 false)
%_18 = load i8, ptr %1, align 8
%2 = zext i8 %_18 to i16
%_47 = lshr i16 2, %2
call void @dump_var(i16 %_47)
ret ptr null
}
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #0
declare void @dump_var(i16)
attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
chenyukang, jyn514 and y21
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-raw-pointersArea: raw pointers, MaybeUninit, NonNullArea: raw pointers, MaybeUninit, NonNullA-rustlantisA miscompilation found by RustlantisA miscompilation found by RustlantisI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.