authorgravatar for jay@jayschwa.netJay Petacat <jay@jayschwa.net> 2023-09-29 23:33:50-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-01 02:39:05-07:00
logd8bfbbbf25984cfdc4d50a92569523a0a151d9e6
tree9452421ad52e61f36cc4090f2edc56285d313bfa
parent376242e586a04b1d2f8f30a329eba3275e0e3a87

std.mem.zeroes: Zero out entire `extern union`, including padding

Fixes #17258

1 files changed, 12 insertions(+), 7 deletions(-)

lib/std/mem.zig+12-7
...@@ -254,7 +254,7 @@ pub fn zeroes(comptime T: type) T {...@@ -254,7 +254,7 @@ pub fn zeroes(comptime T: type) T {
254 var structure: T = undefined;254 var structure: T = undefined;
255 inline for (struct_info.fields) |field| {255 inline for (struct_info.fields) |field| {
256 if (!field.is_comptime) {256 if (!field.is_comptime) {
257 @field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));257 @field(structure, field.name) = zeroes(field.type);
258 }258 }
259 }259 }
260 return structure;260 return structure;
...@@ -292,12 +292,11 @@ pub fn zeroes(comptime T: type) T {...@@ -292,12 +292,11 @@ pub fn zeroes(comptime T: type) T {
292 return @splat(zeroes(info.child));292 return @splat(zeroes(info.child));
293 },293 },
294 .Union => |info| {294 .Union => |info| {
295 if (comptime meta.containerLayout(T) == .Extern) {295 if (info.layout == .Extern) {
296 // The C language specification states that (global) unions296 var item: T = undefined;
297 // should be zero initialized to the first named member.297 @memset(asBytes(&item), 0);
298 return @unionInit(T, info.fields[0].name, zeroes(info.fields[0].type));298 return item;
299 }299 }
300
301 @compileError("Can't set a " ++ @typeName(T) ++ " to zero.");300 @compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
302 },301 },
303 .ErrorUnion,302 .ErrorUnion,
...@@ -318,10 +317,14 @@ pub fn zeroes(comptime T: type) T {...@@ -318,10 +317,14 @@ pub fn zeroes(comptime T: type) T {
318test "zeroes" {317test "zeroes" {
319 const C_struct = extern struct {318 const C_struct = extern struct {
320 x: u32,319 x: u32,
321 y: u32,320 y: u32 align(128),
322 };321 };
323322
324 var a = zeroes(C_struct);323 var a = zeroes(C_struct);
324
325 // Extern structs should have padding zeroed out.
326 try testing.expectEqualSlices(u8, &[_]u8{0} ** @sizeOf(@TypeOf(a)), asBytes(&a));
327
325 a.y += 10;328 a.y += 10;
326329
327 try testing.expect(a.x == 0);330 try testing.expect(a.x == 0);
...@@ -402,9 +405,11 @@ test "zeroes" {...@@ -402,9 +405,11 @@ test "zeroes" {
402405
403 var c = zeroes(C_union);406 var c = zeroes(C_union);
404 try testing.expectEqual(@as(u8, 0), c.a);407 try testing.expectEqual(@as(u8, 0), c.a);
408 try testing.expectEqual(@as(u32, 0), c.b);
405409
406 comptime var comptime_union = zeroes(C_union);410 comptime var comptime_union = zeroes(C_union);
407 try testing.expectEqual(@as(u8, 0), comptime_union.a);411 try testing.expectEqual(@as(u8, 0), comptime_union.a);
412 try testing.expectEqual(@as(u32, 0), comptime_union.b);
408413
409 // Ensure zero sized struct with fields is initialized correctly.414 // Ensure zero sized struct with fields is initialized correctly.
410 _ = zeroes(struct { handle: void });415 _ = zeroes(struct { handle: void });