Closed
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) }
Metadata
Metadata
Assignees
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: raw pointers, MaybeUninit, NonNullA miscompilation found by RustlantisIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessMedium priorityRelevant to the compiler team, which will review and decide on the PR/issue.Performance or correctness regression from one stable version to another.