| Issue |
208611
|
| Summary |
[x86] Incorrect load combining causing OOB reads (and thus segfaults at runtime)
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
scottmcm
|
Context: Rust issue in today's 1.97 release, https://github.com/rust-lang/rust/issues/159035
Rust repro with opt pipeline, https://rust.godbolt.org/z/dTPGY3rY1
Take this LLVM IR, particularly noting that `%0` can be `-1`, `0`, or `1` as conveyed by the `!range` attribute
```llvm
define { i32, i32 } @"example[aafd2ff9cfc6cff8]::run"(ptr dead_on_return noalias nofree noundef readonly align 8 captures(none) dereferenceable(24) %c) unnamed_addr {
start:
%0 = load i64, ptr %c, align 8, !range !4, !noundef !5
%.not = icmp ne i64 %0, -1
%_3.sroa.5.0.c.sroa_idx = getelementptr inbounds nuw i8, ptr %c, i64 12
%_3.sroa.5.0.copyload = load i32, ptr %_3.sroa.5.0.c.sroa_idx, align 4
%1 = trunc nuw i64 %0 to i1
%2 = getelementptr inbounds nuw i8, ptr %c, i64 16
%_3.sroa.6.0.copyload = load i32, ptr %2, align 8
%_4.sroa.0.1 = select i1 %1, i32 %_3.sroa.6.0.copyload, i32 %_3.sroa.5.0.copyload
%_0.sroa.3.0 = select i1 %.not, i32 %_4.sroa.0.1, i32 undef
%_0.sroa.0.0 = zext i1 %.not to i32
%3 = insertvalue { i32, i32 } poison, i32 %_0.sroa.0.0, 0
%4 = insertvalue { i32, i32 } %3, i32 %_0.sroa.3.0, 1
ret { i32, i32 } %4
}
!4 = !{i64 -1, i64 2}
!5 = !{}
```
Today on llc trunk that compiles to the following: <https://llvm.godbolt.org/z/TcY99vhjE>
```asm
"example[aafd2ff9cfc6cff8]::run":
mov rcx, qword ptr [rdi]
xor eax, eax
cmp rcx, -1
setne al
mov ecx, ecx
mov edx, dword ptr [rdi + 4*rcx + 12]
ret
```
`rcx` there maps to `%0`, so it can be `-1`, `0`, or `1` (as i64).
If it stayed that way, that would be fine, as the `[rdi + 4*rcx + 12]` would read 4 bytes from `rdi + 8`, `rdi + 12`, or `rdi + 16`, all of which are within the `dereferenceable(24)`.
However, that `mov ecx, ecx` changes `rcx` to instead be `0x00000000FFFFFFFF`, `0`, or `1` (as i64`), and thus the following `mov` reads massively out of bounds, causing a segfault.
---
Apologies in advance if I got the logic chain wrong here somewhere. I'm reasonably good at middle-end IR but worse at assembly and completely unfamiliar with backend IR.
I think this is x86-specific because it was reported that neither aarch64 nor riscv64gc hit a problem here (Rust Zulip [#t-compiler > Miscompilation in 1.97.0 with new Option::None discriminant @ 💬](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Miscompilation.20in.201.2E97.2E0.20with.20new.20Option.3A.3ANone.20discriminant/near/609362902)).
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs