diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2024-04-29 19:58:09 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-04-30 10:00:53 -0700 |
| commit | 1c9bb6a79de3ca52d819177fea32ce7993634e31 (patch) | |
| tree | b417567646e316854043f775ce6d5c01793153c3 /src/codegen/c.zig | |
| parent | 956f53beb09c07925970453d4c178c6feb53ba70 (diff) | |
| download | zig-1c9bb6a79de3ca52d819177fea32ce7993634e31.tar.gz zig-1c9bb6a79de3ca52d819177fea32ce7993634e31.zip | |
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.
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 8e999a418a..dac7e30b5f 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -6799,11 +6799,27 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { const src_ty = f.typeOf(bin_op.rhs); const writer = f.object.writer(); + if (dest_ty.ptrSize(zcu) != .One) { + try writer.writeAll("if ("); + try writeArrayLen(f, writer, dest_ptr, dest_ty); + try writer.writeAll(" != 0) "); + } try writer.writeAll("memcpy("); try writeSliceOrPtr(f, writer, dest_ptr, dest_ty); try writer.writeAll(", "); try writeSliceOrPtr(f, writer, src_ptr, src_ty); try writer.writeAll(", "); + try writeArrayLen(f, writer, dest_ptr, dest_ty); + try writer.writeAll(" * sizeof("); + try f.renderType(writer, dest_ty.elemType2(zcu)); + try writer.writeAll("));\n"); + + try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + return .none; +} + +fn writeArrayLen(f: *Function, writer: ArrayListWriter, dest_ptr: CValue, dest_ty: Type) !void { + const zcu = f.object.dg.zcu; switch (dest_ty.ptrSize(zcu)) { .One => try writer.print("{}", .{ try f.fmtIntLiteral(try zcu.intValue(Type.usize, dest_ty.childType(zcu).arrayLen(zcu))), @@ -6811,12 +6827,6 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue { .Many, .C => unreachable, .Slice => try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" }), } - try writer.writeAll(" * sizeof("); - try f.renderType(writer, dest_ty.elemType2(zcu)); - try writer.writeAll("));\n"); - - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; } fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue { |
