zig
zig copied to clipboard
MultiArrayList can have unexpected results when combining zero sized fields and optional pointers
Zig Version
0.10.0-dev.3885+a7661f115d
Steps to Reproduce
test.zig
const std = @import("std");
const testing = std.testing;
test {
const S = struct { key: u32, value: void };
const allocator = std.testing.allocator;
var list = std.MultiArrayList(S){};
defer list.deinit(allocator);
try list.append(allocator, .{ .key = 0, .value = {} });
const a: ?*const void = &list.items(.value)[0];
try testing.expect(a != null);
}
$ zig test test.zig
Expected Behavior
All tests pass. We take a pointer to an existing value in the values
slices of the list. We store then store this non null pointer in an optional pointer.
Actual Behavior
Test [1/1] test_0... FAIL (TestUnexpectedResult)
/usr/lib/zig/std/testing.zig:351:14: 0x21168f in expect (test)
if (!ok) return error.TestUnexpectedResult;
^
./test.zig:14:5: 0x2117a0 in test_0 (test)
try testing.expect(a != null);
^
0 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
zig-cache/o/85be9248e4b75e6a5942ec409fcfeca7/test /usr/bin/zig
Basically, the problem here is that list.items(.value)
returns a slice that points to address 0x0
:
const std = @import("std");
const testing = std.testing;
test {
const S = struct { key: u32, value: void };
const allocator = std.testing.allocator;
var list = std.MultiArrayList(S){};
defer list.deinit(allocator);
try list.append(allocator, .{ .key = 0, .value = {} });
std.debug.print("{*}\n", .{list.items(.value).ptr});
}
Test [1/1] test_0... void@0
All 1 tests passed.
Reduction:
test {
std.debug.print("{*}\n", .{foo()});
}
fn foo() []void {
const ptr: [*]void = undefined;
var len: usize = 6;
return ptr[0..len];
}
Also of note is this: https://github.com/ziglang/zig/issues/1831#issuecomment-722129239