Skip to content

Miscompilation from .wrapping_offset(isize::MIN).wrapping_offset(isize::MIN) #112526

Closed

Description

@cbeuw

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) }

cc @RalfJung @nikic

Activity

  1. clubby789 commented on Jun 11, 2023

    @clubby789
    Contributor

    searched nightlies: from nightly-2022-06-01 to nightly-2023-06-11
    regressed nightly: nightly-2023-03-26
    searched commit range: 8be3c2b...0c61c7a
    regressed commit: 0c61c7a -> #109474 -> LLVM 16 upgrade

    bisected with cargo-bisect-rustc v0.6.6

    Host triple: x86_64-unknown-linux-gnu
    Reproduce with:

    cargo bisect-rustc --start 2022-06-01 --script script.sh --prompt 
  2. added
    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.
    on Jun 11, 2023
  3. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
    on Jun 11, 2023
  4. added
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jun 11, 2023
  5. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    A-raw-pointersArea: raw pointers, MaybeUninit, NonNull
    on Jun 11, 2023
  6. self-assigned this
    on Jun 12, 2023
  7. nikic commented on Jun 12, 2023

    @nikic
    Contributor
  8. apiraino commented on Jun 12, 2023

    @apiraino
    Contributor

    WG-prioritization assigning priority (Zulip discussion).

    @rustbot label -I-prioritize +P-medium

  9. added and removed
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jun 12, 2023
  10. nikic commented on Jul 3, 2023

    @nikic
    Contributor

    This has been fixed upstream.

  11. nikic commented on Aug 13, 2023

    @nikic
    Contributor
  12. added
    S-found-by-fuzzingStatus: This issue was found using fuzzing. It may not arise in practical cases.
    on Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-raw-pointersArea: raw pointers, MaybeUninit, NonNullA-rustlantisArea: A miscompilation found by RustlantisI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityS-found-by-fuzzingStatus: This issue was found using fuzzing. It may not arise in practical cases.T-compilerRelevant 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.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions