zig icon indicating copy to clipboard operation
zig copied to clipboard

"reinterpret extern union" behavior test causing undefined behavior in the compiler

Open andrewrk opened this issue 1 year ago • 0 comments

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.

andrewrk avatar Mar 22 '24 03:03 andrewrk