Skip to content

Commit d8bfbbb

Browse files
jayschwaandrewrk
authored andcommitted
std.mem.zeroes: Zero out entire extern union, including padding
Fixes #17258
1 parent 376242e commit d8bfbbb

File tree

1 file changed

+12
-7
lines changed

1 file changed

+12
-7
lines changed

lib/std/mem.zig

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub fn zeroes(comptime T: type) T {
254254
var structure: T = undefined;
255255
inline for (struct_info.fields) |field| {
256256
if (!field.is_comptime) {
257-
@field(structure, field.name) = zeroes(@TypeOf(@field(structure, field.name)));
257+
@field(structure, field.name) = zeroes(field.type);
258258
}
259259
}
260260
return structure;
@@ -292,12 +292,11 @@ pub fn zeroes(comptime T: type) T {
292292
return @splat(zeroes(info.child));
293293
},
294294
.Union => |info| {
295-
if (comptime meta.containerLayout(T) == .Extern) {
296-
// The C language specification states that (global) unions
297-
// should be zero initialized to the first named member.
298-
return @unionInit(T, info.fields[0].name, zeroes(info.fields[0].type));
295+
if (info.layout == .Extern) {
296+
var item: T = undefined;
297+
@memset(asBytes(&item), 0);
298+
return item;
299299
}
300-
301300
@compileError("Can't set a " ++ @typeName(T) ++ " to zero.");
302301
},
303302
.ErrorUnion,
@@ -318,10 +317,14 @@ pub fn zeroes(comptime T: type) T {
318317
test "zeroes" {
319318
const C_struct = extern struct {
320319
x: u32,
321-
y: u32,
320+
y: u32 align(128),
322321
};
323322

324323
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+
325328
a.y += 10;
326329

327330
try testing.expect(a.x == 0);
@@ -402,9 +405,11 @@ test "zeroes" {
402405

403406
var c = zeroes(C_union);
404407
try testing.expectEqual(@as(u8, 0), c.a);
408+
try testing.expectEqual(@as(u32, 0), c.b);
405409

406410
comptime var comptime_union = zeroes(C_union);
407411
try testing.expectEqual(@as(u8, 0), comptime_union.a);
412+
try testing.expectEqual(@as(u32, 0), comptime_union.b);
408413

409414
// Ensure zero sized struct with fields is initialized correctly.
410415
_ = zeroes(struct { handle: void });

0 commit comments

Comments
 (0)