Skip to content

Commit 1c9bb6a

Browse files
committed
C backend: avoid memcpy when len=0
As of Clang 18, calling memcpy() with a misaligned pointer trips UBSAN, even if the length is zero. This unfortunately includes any call to `@memcpy` when source or destination are undefined and the length is zero. This patch makes the C backend avoid calling memcpy when the length is zero, thereby avoiding undefined behavior. A zig1.wasm update will be needed in the llvm18 branch to activate this code.
1 parent 956f53b commit 1c9bb6a

File tree

1 file changed

+16
-6
lines changed

1 file changed

+16
-6
lines changed

src/codegen/c.zig

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6799,24 +6799,34 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
67996799
const src_ty = f.typeOf(bin_op.rhs);
68006800
const writer = f.object.writer();
68016801

6802+
if (dest_ty.ptrSize(zcu) != .One) {
6803+
try writer.writeAll("if (");
6804+
try writeArrayLen(f, writer, dest_ptr, dest_ty);
6805+
try writer.writeAll(" != 0) ");
6806+
}
68026807
try writer.writeAll("memcpy(");
68036808
try writeSliceOrPtr(f, writer, dest_ptr, dest_ty);
68046809
try writer.writeAll(", ");
68056810
try writeSliceOrPtr(f, writer, src_ptr, src_ty);
68066811
try writer.writeAll(", ");
6812+
try writeArrayLen(f, writer, dest_ptr, dest_ty);
6813+
try writer.writeAll(" * sizeof(");
6814+
try f.renderType(writer, dest_ty.elemType2(zcu));
6815+
try writer.writeAll("));\n");
6816+
6817+
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6818+
return .none;
6819+
}
6820+
6821+
fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void {
6822+
const zcu = f.object.dg.zcu;
68076823
switch (dest_ty.ptrSize(zcu)) {
68086824
.One => try writer.print("{}", .{
68096825
try f.fmtIntLiteral(try zcu.intValue(Type.usize, dest_ty.childType(zcu).arrayLen(zcu))),
68106826
}),
68116827
.Many, .C => unreachable,
68126828
.Slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }),
68136829
}
6814-
try writer.writeAll(" * sizeof(");
6815-
try f.renderType(writer, dest_ty.elemType2(zcu));
6816-
try writer.writeAll("));\n");
6817-
6818-
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6819-
return .none;
68206830
}
68216831

68226832
fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {

0 commit comments

Comments
 (0)