#Incorrect upcast in Reader

1 messages · Page 1 of 1 (latest)

austere frost
#

File descriptor lost after cast
std.fs.File.Reader -> std.io.AnyReader

zig version
0.12.0-dev.1753+a98d4a66e

For simplicity, I copied the cast into my code with a reference to the original

const std = @import("std");

fn print(comptime step: []const u8, d: *const anyopaque) void {
    const v: *const std.fs.File = @alignCast(@ptrCast(d));
    std.log.info("\t{s}  \t->\tfd={}", .{ step, v.handle });
}

// **********

// copy from lib/std/io/Reader.zig
const AnyReader = struct {
    context: *const anyopaque,
    readFn: *const fn (context: *const anyopaque, buffer: []u8) anyerror!usize,

    pub fn read(self: AnyReader, buffer: []u8) anyerror!usize {
        return self.readFn(self.context, buffer);
    }
};

// copy from lib/std/io.zig:320
pub fn any(self: *const std.fs.File.Reader) AnyReader {
    const v: *const anyopaque = @ptrCast(&self.context);
    print("point any.1", v);
    return .{
        .context = v,
        .readFn = typeErasedReadFn,
    };
}

// copy from lib/std/io.zig:329
fn typeErasedReadFn(context: *const anyopaque, buffer: []u8) anyerror!usize {
    const ptr: *const std.fs.File = @alignCast(@ptrCast(context));
    return std.fs.File.read(ptr.*, buffer);
}

// **********

pub fn parse(result: std.fs.File) AnyReader {
    const ret = any(&result.reader());
    print("point parse.1", ret.context);
    return ret;
}

pub fn main() !void {
    var result = try std.fs.cwd().createFile("1.txt", .{});
    defer result.close();

    const ret = parse(result);
    // if use below, it will be ok
    // const ret = any(&result.reader());

    const vv: *const std.fs.File = @alignCast(@ptrCast(ret.context));
    std.log.info("\tpoint 2  \t->\tfd={}", .{vv.handle});
    print("point 2.1", ret.context);

    var block: [1024]u8 = undefined;
    print("point 3", ret.context);
    const read = try ret.read(block[0..]);
    _ = read;
}
#
info:   point any.1     ->      fd=3
info:   point parse.1   ->      fd=3
info:   point 2         ->      fd=3
info:   point 2.1       ->      fd=1
info:   point 3         ->      fd=1

I feel that the problem is in parse
When I cast to AnyReader not in the parse function but in main, the file descriptor is not lost

amber flare
#

&result.reader() is taking the address of a local variable, the memory it points to goes out of scope when parse returns