mirror of
https://github.com/ziglang/zig.git
synced 2025-12-07 14:53:08 +00:00
LLVM: fix missing alignment on wrapping instructions
Previously, when lowering AIR instructions `wrap_errunion_payload`, `wrap_errunion_err`, and `wrap_optional`, the LLVM backend would create an alloca instruction to store the result, but did not set the alignment on it. This caused UB which went undetected for a long time until we started enabling the stack protector. Closes #12594 Unblocks #12508 Inspires #12634 Tests passed locally: * test-behavior * test-cases
This commit is contained in:
parent
9d231c4991
commit
d2ad8afff4
@ -6188,7 +6188,9 @@ pub const FuncGen = struct {
|
|||||||
}
|
}
|
||||||
const llvm_optional_ty = try self.dg.lowerType(optional_ty);
|
const llvm_optional_ty = try self.dg.lowerType(optional_ty);
|
||||||
if (isByRef(optional_ty)) {
|
if (isByRef(optional_ty)) {
|
||||||
|
const target = self.dg.module.getTarget();
|
||||||
const optional_ptr = self.buildAlloca(llvm_optional_ty);
|
const optional_ptr = self.buildAlloca(llvm_optional_ty);
|
||||||
|
optional_ptr.setAlignment(optional_ty.abiAlignment(target));
|
||||||
const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, "");
|
const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, "");
|
||||||
var ptr_ty_payload: Type.Payload.ElemType = .{
|
var ptr_ty_payload: Type.Payload.ElemType = .{
|
||||||
.base = .{ .tag = .single_mut_pointer },
|
.base = .{ .tag = .single_mut_pointer },
|
||||||
@ -6208,20 +6210,21 @@ pub const FuncGen = struct {
|
|||||||
if (self.liveness.isUnused(inst)) return null;
|
if (self.liveness.isUnused(inst)) return null;
|
||||||
|
|
||||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||||
const inst_ty = self.air.typeOfIndex(inst);
|
const err_un_ty = self.air.typeOfIndex(inst);
|
||||||
const operand = try self.resolveInst(ty_op.operand);
|
const operand = try self.resolveInst(ty_op.operand);
|
||||||
const payload_ty = self.air.typeOf(ty_op.operand);
|
const payload_ty = self.air.typeOf(ty_op.operand);
|
||||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
|
||||||
return operand;
|
return operand;
|
||||||
}
|
}
|
||||||
const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull();
|
const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull();
|
||||||
const err_un_llvm_ty = try self.dg.lowerType(inst_ty);
|
const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);
|
||||||
|
|
||||||
const target = self.dg.module.getTarget();
|
const target = self.dg.module.getTarget();
|
||||||
const payload_offset = errUnionPayloadOffset(payload_ty, target);
|
const payload_offset = errUnionPayloadOffset(payload_ty, target);
|
||||||
const error_offset = errUnionErrorOffset(payload_ty, target);
|
const error_offset = errUnionErrorOffset(payload_ty, target);
|
||||||
if (isByRef(inst_ty)) {
|
if (isByRef(err_un_ty)) {
|
||||||
const result_ptr = self.buildAlloca(err_un_llvm_ty);
|
const result_ptr = self.buildAlloca(err_un_llvm_ty);
|
||||||
|
result_ptr.setAlignment(err_un_ty.abiAlignment(target));
|
||||||
const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, "");
|
const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, "");
|
||||||
const store_inst = self.builder.buildStore(ok_err_code, err_ptr);
|
const store_inst = self.builder.buildStore(ok_err_code, err_ptr);
|
||||||
store_inst.setAlignment(Type.anyerror.abiAlignment(target));
|
store_inst.setAlignment(Type.anyerror.abiAlignment(target));
|
||||||
@ -6256,6 +6259,7 @@ pub const FuncGen = struct {
|
|||||||
const error_offset = errUnionErrorOffset(payload_ty, target);
|
const error_offset = errUnionErrorOffset(payload_ty, target);
|
||||||
if (isByRef(err_un_ty)) {
|
if (isByRef(err_un_ty)) {
|
||||||
const result_ptr = self.buildAlloca(err_un_llvm_ty);
|
const result_ptr = self.buildAlloca(err_un_llvm_ty);
|
||||||
|
result_ptr.setAlignment(err_un_ty.abiAlignment(target));
|
||||||
const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, "");
|
const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, "");
|
||||||
const store_inst = self.builder.buildStore(operand, err_ptr);
|
const store_inst = self.builder.buildStore(operand, err_ptr);
|
||||||
store_inst.setAlignment(Type.anyerror.abiAlignment(target));
|
store_inst.setAlignment(Type.anyerror.abiAlignment(target));
|
||||||
|
|||||||
@ -796,3 +796,19 @@ test "error union of noreturn used with catch" {
|
|||||||
const err = NoReturn.testCatch();
|
const err = NoReturn.testCatch();
|
||||||
try expect(err == error.OtherFailure);
|
try expect(err == error.OtherFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "alignment of wrapping an error union payload" {
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
|
const S = struct {
|
||||||
|
const I = extern struct { x: i128 };
|
||||||
|
|
||||||
|
fn foo() anyerror!I {
|
||||||
|
var i: I = .{ .x = 1234 };
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try expect((S.foo() catch unreachable).x == 1234);
|
||||||
|
}
|
||||||
|
|||||||
@ -412,3 +412,19 @@ test "orelse on C pointer" {
|
|||||||
const d = foo orelse @compileError("bad");
|
const d = foo orelse @compileError("bad");
|
||||||
try expectEqual([*c]const u8, @TypeOf(d));
|
try expectEqual([*c]const u8, @TypeOf(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "alignment of wrapping an optional payload" {
|
||||||
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|
||||||
|
const S = struct {
|
||||||
|
const I = extern struct { x: i128 };
|
||||||
|
|
||||||
|
fn foo() ?I {
|
||||||
|
var i: I = .{ .x = 1234 };
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try expect(S.foo().?.x == 1234);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user