Repository navigation
struct field load through underaligned pointer has incorrect alignment #14904
Copy link
Copy link
Closed
Labels
backend-cThe C backend (CBE) outputs C source code.The C backend (CBE) outputs C source code.bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.Tokenization, parsing, AstGen, Sema, and Liveness.miscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.regressionIt worked in a previous version of Zig, but stopped working.It worked in a previous version of Zig, but stopped working.
Milestone
Description
Zig Version
0.11.0-dev.1969+d525ecb52
Steps to Reproduce and Observed Behavior
const std = @import("std");
const expect = std.testing.expect;
pub fn main() !void {
var buf: [9]u8 align(4) = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const ptr = @ptrCast(*align(1) Header, buf[1..][0..8]);
const x = ptr.bytes_len;
std.debug.print("x=0x{x}\n", .{x});
}
const Header = extern struct {
tag: u32,
bytes_len: u32,
};$ stage3/bin/zig build-exe test3.zig -target mipsel-linux-musl
$ qemu-mipsel ./test3
Bus error (core dumped)
The problem is incorrect alignment in the LLVM IR:
const std = @import("std");
pub fn panic(msg: []const u8, st: ?*std.builtin.StackTrace, start: ?usize) noreturn {
_ = .{ msg, st, start };
unreachable;
}
export fn entry() bool {
doTheTest() catch return false;
return true;
}
fn doTheTest() !void {
var buf: [9]u8 align(4) = .{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const ptr: *align(1) Header = @ptrCast(buf[1..][0..8]);
const x = ptr.bytes_len;
foo(x);
}
extern fn foo(u32) void;
const Header = extern struct {
tag: u32,
bytes_len: u32,
};$ stage3/bin/zig build-obj test2.zig -target mipsel-linux-musl --verbose-llvm-ir -fstrip -OReleaseFast
define internal fastcc i16 @test2.doTheTest() unnamed_addr #0 {
Entry:
%0 = alloca ptr, align 4
%1 = alloca [9 x i8], align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %1, ptr align 1 @0, i32 9, i1 false)
%2 = getelementptr inbounds [9 x i8], ptr %1, i32 0, i32 1
store ptr %2, ptr %0, align 4
%3 = load ptr, ptr %0, align 4
%4 = getelementptr inbounds [8 x i8], ptr %3, i32 0, i32 0
%5 = getelementptr inbounds %test2.Header, ptr %4, i32 0, i32 1
%6 = load i32, ptr %5, align 4
call void @foo(i32 %6)
ret i16 0
}The problem is %6 = load i32, ptr %5, align 4 which has align 4 instead of align 1.
Side note: it is very annoying that the panic override above does not eliminate panicOutOfBounds from calling into std.debug.panicExtra and dragging in a whole lot of formatting code.
I have no evidence this is a regression, but I suspect it is.
Expected Behavior
I expect to see %6 = load i32, ptr %5, align 1 which would cause LLVM to generate machine code that did not cause a Bus Error.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
backend-cThe C backend (CBE) outputs C source code.The C backend (CBE) outputs C source code.bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviorfrontendTokenization, parsing, AstGen, Sema, and Liveness.Tokenization, parsing, AstGen, Sema, and Liveness.miscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.regressionIt worked in a previous version of Zig, but stopped working.It worked in a previous version of Zig, but stopped working.
Activity
add a workaround for miscompilation regarding alignment
add a workaround for miscompilation regarding alignment
add a workaround for miscompilation regarding alignment
add a workaround for miscompilation regarding alignment
add a workaround for miscompilation regarding alignment
add behavior test for resolved alignment issue
add behavior test for sub-aligned field access
andrewrk commentedon Aug 1, 2023
Fixed for the LLVM backend; issue remains for the C backend.
add behavior test for sub-aligned field access
add behavior test for sub-aligned field access
add behavior test for sub-aligned field access
andrewrk commentedon Mar 28, 2024
C code generated is now:
The
memcpymakes it safe. Not sure when this got fixed.andrewrk commentedon Mar 28, 2024
Hmm the actual behavior test is not fixed however:
Looks like the pointer cast causes UB even though the pointer is not accessed.
cbe: rewrite `CType`
cbe: rewrite `CType`
cbe: rewrite `CType`
cbe: rewrite `CType`