zig
zig copied to clipboard
"reinterpret extern union" behavior test causing undefined behavior in the compiler
Zig Version
0.12.0-dev.3405+31791ae15
Steps to Reproduce and Observed Behavior
fn littleToNativeEndian(comptime T: type, v: T) T {
return if (endian == .little) v else @byteSwap(v);
}
test "reinterpret extern union" {
const U = extern union {
foo: u8,
baz: u32 align(8),
bar: u32,
};
const S = struct {
fn doTheTest() !void {
{
// Undefined initialization
const u = blk: {
var u: U = undefined;
@memset(std.mem.asBytes(&u), 0);
u.bar = 0xbbbbbbbb;
u.foo = 0x2a;
break :blk u;
};
try expectEqual(@as(u8, 0x2a), u.foo);
try expectEqual(littleToNativeEndian(u32, 0xbbbbbb2a), u.bar);
try expectEqual(littleToNativeEndian(u32, 0xbbbbbb2a), u.baz);
}
{
// Union initialization
var u: U = .{
.foo = 0x2a,
};
{
const expected, const mask = switch (endian) {
.little => .{ 0x2a, 0xff },
.big => .{ 0x2a000000, 0xff000000 },
};
try expectEqual(@as(u8, 0x2a), u.foo);
try expectEqual(@as(u32, expected), u.bar & mask);
try expectEqual(@as(u32, expected), u.baz & mask);
}
// Writing to a larger field
u.baz = 0xbbbbbbbb;
try expectEqual(@as(u8, 0xbb), u.foo);
try expectEqual(@as(u32, 0xbbbbbbbb), u.bar);
try expectEqual(@as(u32, 0xbbbbbbbb), u.baz);
// Writing to the same field
u.baz = 0xcccccccc;
try expectEqual(@as(u8, 0xcc), u.foo);
try expectEqual(@as(u32, 0xcccccccc), u.bar);
try expectEqual(@as(u32, 0xcccccccc), u.baz);
// Writing to a smaller field
u.foo = 0xdd;
try expectEqual(@as(u8, 0xdd), u.foo);
try expectEqual(littleToNativeEndian(u32, 0xccccccdd), u.bar);
try expectEqual(littleToNativeEndian(u32, 0xccccccdd), u.baz);
}
}
};
try comptime S.doTheTest();
}
$ valgrind debug/bin/zig test example.zig -fno-emit-bin
==1662211== Thread 1:
==1662211== Conditional jump or move depends on uninitialised value(s)
==1662211== at 0x643A894: math.big.int.calcLimbLen__anon_89347 (int.zig:28)
==1662211== by 0x6128550: math.big.int.Mutable.set__anon_78775 (int.zig:232)
==1662211== by 0x5E58728: math.big.int.Mutable.init__anon_63941 (int.zig:178)
==1662211== by 0x6654DF0: InternPool.Key.Int.Storage.toBigInt (InternPool.zig:929)
==1662211== by 0x691F720: InternPool.Key.hash64 (InternPool.zig:1137)
==1662211== by 0x6431A57: InternPool.Key.hash32 (InternPool.zig:1065)
==1662211== by 0x6123366: InternPool.KeyAdapter.hash (InternPool.zig:358)
==1662211== by 0x612455A: checkedHash (array_hash_map.zig:1841)
==1662211== by 0x612455A: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutInternal__anon_78747 (array_hash_map.zig:1658)
==1662211== by 0x5E546B5: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutAssumeCapacityAdapted__anon_63790 (array_hash_map.zig:816)
==1662211== by 0x5E5383D: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutContextAdapted__anon_63786 (array_hash_map.zig:753)
==1662211== by 0x5E54795: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutAdapted__anon_63785 (array_hash_map.zig:738)
==1662211== by 0x5C62D55: InternPool.get (InternPool.zig:4992)
==1662211==
==1662211== Conditional jump or move depends on uninitialised value(s)
==1662211== at 0x5C01157: debug.assert (debug.zig:403)
==1662211== by 0x690229D: math.log2_int__anon_104847 (math.zig:1347)
==1662211== by 0x65F7A20: math.log2.log2__anon_92960 (log2.zig:39)
==1662211== by 0x643A8A4: math.big.int.calcLimbLen__anon_89347 (int.zig:33)
==1662211== by 0x6128550: math.big.int.Mutable.set__anon_78775 (int.zig:232)
==1662211== by 0x5E58728: math.big.int.Mutable.init__anon_63941 (int.zig:178)
==1662211== by 0x6654DF0: InternPool.Key.Int.Storage.toBigInt (InternPool.zig:929)
==1662211== by 0x691F720: InternPool.Key.hash64 (InternPool.zig:1137)
==1662211== by 0x6431A57: InternPool.Key.hash32 (InternPool.zig:1065)
==1662211== by 0x6123366: InternPool.KeyAdapter.hash (InternPool.zig:358)
==1662211== by 0x612455A: checkedHash (array_hash_map.zig:1841)
==1662211== by 0x612455A: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutInternal__anon_78747 (array_hash_map.zig:1658)
==1662211== by 0x5E546B5: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutAssumeCapacityAdapted__anon_63790 (array_hash_map.zig:816)
==1662211==
==1662211== Conditional jump or move depends on uninitialised value(s)
==1662211== at 0x69022BA: math.log2_int__anon_104847 (math.zig:1348)
==1662211== by 0x65F7A20: math.log2.log2__anon_92960 (log2.zig:39)
==1662211== by 0x643A8A4: math.big.int.calcLimbLen__anon_89347 (int.zig:33)
==1662211== by 0x6128550: math.big.int.Mutable.set__anon_78775 (int.zig:232)
==1662211== by 0x5E58728: math.big.int.Mutable.init__anon_63941 (int.zig:178)
==1662211== by 0x6654DF0: InternPool.Key.Int.Storage.toBigInt (InternPool.zig:929)
==1662211== by 0x691F720: InternPool.Key.hash64 (InternPool.zig:1137)
==1662211== by 0x6431A57: InternPool.Key.hash32 (InternPool.zig:1065)
==1662211== by 0x6123366: InternPool.KeyAdapter.hash (InternPool.zig:358)
==1662211== by 0x612455A: checkedHash (array_hash_map.zig:1841)
==1662211== by 0x612455A: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutInternal__anon_78747 (array_hash_map.zig:1658)
==1662211== by 0x5E546B5: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutAssumeCapacityAdapted__anon_63790 (array_hash_map.zig:816)
==1662211== by 0x5E5383D: array_hash_map.ArrayHashMapUnmanaged(void,void,array_hash_map.AutoContext(void),true).getOrPutContextAdapted__anon_63786 (array_hash_map.zig:753)
Expected Behavior
No Valgrind errors.