zig
zig copied to clipboard
`read`, etc. should check `slice.len == 0`
Zig Version
0.10.0-dev.2103+ac1aaec9c
Steps to Reproduce
Consider this program:
const std = @import("std");
const debug = std.debug;
pub fn main() void {
var array: [0]u8 = [_]u8{};
var slice: []u8 = &array;
const ptr = @ptrToInt(slice.ptr);
debug.print("ptr: 0x{x}\n", .{ptr});
}
A problem with the current behavior is that passing a zero length buffer to read
will crash the program (close
returns EFAULT
):
const std = @import("std");
const io = std.io;
pub fn main() !void {
const stdin = io.getStdIn();
var buf: [0]u8 = [_]u8{};
_ = try stdin.read(&buf);
}
This C program works as expected: https://glot.io/snippets/g9k7ypryux. This Go program also works as expected: https://go.dev/play/p/5LcVU6It_xZ
Expected Behavior
The output to be:
ptr: 0
Actual Behavior
The output is:
ptr: 0xaaaaaaaaaaaaaaaa
that is, undefined.
Why do you expect the pointer to be 0
? That is not even a value allowed by the type.
@Vexu, indeed it does not need to be 0
. In order for the read
example to work, it just needs to be a valid pointer.
Thanks.
But what should it be a pointer too?
[0]u8
is zero size so doesn't exist in memory at runtime, so you can't get its address.
@leecannon, I think https://github.com/ziglang/zig/issues/6706 should solve this problem.
Current behavior does not feels right, to me. You can not get the address of [0]u
, but you can coerce it to a slice, whose .ptr
field holds an undefined pointer.
It seems that there is another "unexpected" behavior with empty slices:
test "empty slice ptr from zero bit array" {
const a: [0]u8 = [_]u8{};
var b: []u8 = &a;
debug.print("len b: {}\n", .{b.len});
}
test "empty slice ptr" {
const a: []u8 = try testing.allocator.alloc(u8, 10);
defer testing.allocator.free(a);
var b: []u8 = a[0..0];
debug.print("len b: {}\n", .{b.len});
try testing.expectEqual(a.ptr, b.ptr);
}
Both are empty slices, but the latter has a valid pointer.
Code adapted from https://github.com/ziglang/zig/issues/4771.
Thanks.
@Vexu, indeed it does not need to be
0
. In order for theread
example to work, it just needs to be a valid pointer.
Sounds like the actual bug is read
not checking whether the slice has a non zero length before doing any operations on the pointer.
It seems that there is another "unexpected" behavior with empty slices:
I would find it more unexpected for slicing to turn an invalid pointer into a valid one or the other way around. The key property for both of these slices is the length being zero.
I think this issue can be closed after commit d0eef26.