-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rustdoc crashing on linux-sparc64 due to unaligned access #56927
Comments
Looking at the build log (https://buildd.debian.org/status/fetch.php?pkg=rustc&arch=sparc64&ver=1.31.0%2Bdfsg1-2&stamp=1545047706&raw=0), it looks like it's affecting |
Would it be possible to disassemble the function in question? Does the failure occur with the official builds? If so, bisecting with I would do it myself, but I’ve been unsuccessful in setting up sparc VMs (installed debian fails to boot, and I haven’t gotten around to dealing with it yet).
|
I am currently bisecting this, I'm almost there :). As for SPARC machines, we have set up a SPARC T5 VM in the gcc compile farm which every developer can use who applies for a free account at the gcc compile farm, see: https://gcc.gnu.org/wiki/CompileFarm There are both SPARC machines running Linux as well as Solaris available. |
Found the commit which introduced the bug:
|
This smellls similar to #56267, although the fixes for that particular problem have been backported and are available in stable and the lint pass does not complain about pulldown_cmark in any way... |
discussed at T-compiler meeting. P-high, since this may be symptom of broader UB beyond the case outlined here. |
Since you guys don't run tests on sparc64, is there a way to write a test for this that crashes on x86-64? I originally told @glaubitz to ignore the sparc64 failures but it looks like it was good that he chased it down! |
We have codegen tests which do not depend on test being run (checks the generated LLVM-IR/Assembly/etc), and so can be run on any host. |
Ok, here's a reduced test case that shows the incorrect output produced by rustc: pub struct RawParser {
// Unused but necessary; only reproduces when active_tab isn't the
// first field.
off: usize,
active_tab: [u8; 256],
}
impl RawParser {
pub fn init_active(&mut self) {
for &c in b"\x00\t\n\r_\\&*[!`<" {
self.active_tab[c as usize] = 1;
}
}
} This then generates the following IR (you need ; lib::RawParser:: init_active
; Function Attrs: nounwind uwtable
define void @_ZN3lib9RawParser11init_active17hda1bc094c972134fE(%RawParser* nocapture dereferenceable(264) %self) unnamed_addr #0 {
start:
%0 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 0
store i8 1, i8* %0, align 8
%1 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 9
store i8 1, i8* %1, align 8
%2 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 10
store i8 1, i8* %2, align 8
%3 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 13
store i8 1, i8* %3, align 8
%4 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 95
store i8 1, i8* %4, align 8
%5 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 92
store i8 1, i8* %5, align 8
%6 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 38
store i8 1, i8* %6, align 8
%7 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 42
store i8 1, i8* %7, align 8
%8 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 91
store i8 1, i8* %8, align 8
%9 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 33
store i8 1, i8* %9, align 8
%10 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 96
store i8 1, i8* %10, align 8
%11 = getelementptr inbounds %RawParser, %RawParser* %self, i64 0, i32 3, i64 60
store i8 1, i8* %11, align 8
ret void
} These elements are obviously not all 8-byte aligned, but the result is that LLVM combines adjacent stores, specifically 9/10, 91/92 and 95/96, into I believe the problem is in pub fn project_index<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
&self,
bx: &mut Bx,
llindex: V
) -> Self {
PlaceRef {
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
llextra: None,
layout: self.layout.field(bx.cx(), 0),
align: self.align
}
} Specifically, the array itself is aligned to 8 bytes and so the mentioned PR is correct to not force the array to be assumed aligned only to 1 byte (as was happening before with the extra Finally, here's a more minimal test case that doesn't try to look like the code from pulldown-cmark: pub struct S {
pad: usize,
arr: [u8; 3],
}
impl S {
pub fn f(&mut self) {
self.arr[1] = 0;
self.arr[2] = 0;
}
} This gives (still with ; min::S::f
; Function Attrs: norecurse nounwind uwtable
define void @_ZN3min1S1f17h1ac21da989830415E(%S* nocapture dereferenceable(16) %self) unnamed_addr #0 {
start:
%0 = getelementptr inbounds %S, %S* %self, i64 0, i32 3, i64 1
store i8 0, i8* %0, align 8
%1 = getelementptr inbounds %S, %S* %self, i64 0, i32 3, i64 2
store i8 0, i8* %1, align 8
ret void
} |
Ugh, we already fixed two very similar issues, and this is the third. Reviewing other code that generates GEPs, we also have the same issue with Repeat handling:
Generates:
Notably, that |
I think something like this is what you want: pub fn project_index<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
&self,
bx: &mut Bx,
llindex: V
) -> Self {
let index = if bx.cx().is_const_integral(llindex) { bx.cx().const_to_uint(llindex) } else { 1 };
let layout = self.layout.field(bx.cx(), 0);
PlaceRef {
llval: bx.inbounds_gep(self.llval, &[bx.cx().const_usize(0), llindex]),
llextra: None,
layout: layout,
align: self.align.restrict_for_offset(index * layout.size)
}
} |
I've submitted #57053 to fix both issues. |
Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, use the element size, as this will yield the minimum possible alignment. This handles both direct array indexing, and array repeat expressions. Fixes rust-lang#56927. r? @nagisa
Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, use the element size, as this will yield the minimum possible alignment. This handles both direct array indexing, and array repeat expressions. Fixes rust-lang#56927. r? @nagisa
Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, use the element size, as this will yield the minimum possible alignment. This handles both direct array indexing, and array repeat expressions. Fixes rust-lang#56927. r? @nagisa
Fix alignment for array indexing We need to reduce the alignment with the used offset. If the offset isn't known, use the element size, as this will yield the minimum possible alignment. This handles both direct array indexing, and array repeat expressions. Fixes rust-lang#56927. r? @nagisa
Reopening to track beta backport. |
Beta backport landed as part of #57305. |
Since version 1.31.0,
rustdoc
crashes when running the testsrc/test/run-make-fulldeps/rustdoc-error-lines
:I have not worked out yet whether this is a regression in the Rust compiler itself such that it generates code with unaligned access (we had this before) or whether
rustdoc
itself contains broken code.CC @jrtc27 @psumbera @karcherm
The text was updated successfully, but these errors were encountered: