Skip to content

Windows 7 i686 does not reliably align 16 byte aligned thread locals #138903

Closed

Description

@drewkett

The following program will reliably crash using the i686-win7-windows-msvc target on a Windows 7 installation using latest nightly.

I tried this code:

#[repr(align(16))]
struct Align16(u8);

thread_local! {
    static ALIGN16: Align16 = Align16(0);
}

fn main() {
    let mut threads = Vec::new();
    for _ in 0..10 {
        threads.push(std::thread::spawn(|| {
            ALIGN16.with(|r| println!("ALIGN16 {:p}", r as *const _));
        }));
    }
    for thread in threads {
        thread.join().unwrap();
    }
}

This reliably produces the following panic.

unsafe precondition(s) violated: ptr::replace requires that the pointer argument is aligned and non-null

This indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread caused a non-unwinding panic. aborting.

My experience with/understanding of thread locals is mostly limited to what i've researched due to this issue, but it does appear that an i686 targeted executable on Windows 7 does not reliably align thread locals when 16 byte alignment is requested. I didn't see issues with even 8 byte alignment. I was not able to reproduce this issue on Windows 10.

Given that i686 win7 is a likely pretty niche target, do you think it would be reasonable to partially undo #123257 by disabling has_thread_local for i686-win7-windows-msvc. It seems that i686 on Windows 7 can't be trusted for alignment of thread locals. I did test adjusting the i686-win7-windows-msvc target in a local build of the compiler and it does appear to work for the test program.

The 16 byte aligned thread local came from matrixmultiply which actually works around misalignment internally, but compiled this way I get the UB check panic anyway. I can certainly work around it by seeing if matrixmultiply can be patched, or just doing that locally. But it seems like this should be fixed in the compiler ideally.

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Mar 24, 2025
  2. moxian commented on Mar 24, 2025

    @moxian
    Contributor

    @rustbot label: +O-windows-7 +O-x86_32 +A-thread-locals +A-align -needs-triage +T-compiler
    cc @roblabla @ChrisDenton

  3. added
    A-alignArea: alignment control (`repr(align(N))` and so on)
    A-thread-localsArea: Thread local storage (TLS)
    O-windows-7OS: Windows 7 or Windows Server 2008 R2 or etc.
    O-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Mar 24, 2025
  4. roblabla commented on Apr 18, 2025

    @roblabla
    Contributor

    So I dug into this a bit, and was able to reproduce. Thankfully there's a bit of a similar issue in GNU targets, with some instructions on how to investigate: #135719 (comment)

    llvm-objdump --all gives me the following information:

    TLS directory:
      StartAddressOfRawData: 0x444000
      EndAddressOfRawData: 0x444064
      AddressOfIndex: 0x442a0c
      AddressOfCallBacks: 0x43e804
      SizeOfZeroFill: 0
      Characteristics: 5242880
      Alignment: 16
    

    Characteristics 5242880 is 0x500000 in hex, which equals IMAGE_SCN_ALIGN_16BYTES, which matches what we expect. However, when running the reproducer, I indeed get the same crashes. So this would indicate that Windows 7 does not respect the IMAGE_SCN_ALIGN_16BYTES flag in the TLS directory.

    I'll make a PR to put has_thread_local back to false.

  5. added 2 commits that reference this issue on Apr 18, 2025
    318226a
    b7b3dde
  6. added a commit that references this issue on Apr 19, 2025
    1aeb903
  7. added a commit that references this issue on Apr 19, 2025
    67a97ba
  8. added a commit that references this issue on Apr 19, 2025
    4c5bccc
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-alignArea: alignment control (`repr(align(N))` and so on)A-thread-localsArea: Thread local storage (TLS)C-bugCategory: This is a bug.O-windows-7OS: Windows 7 or Windows Server 2008 R2 or etc.O-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)T-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