Skip to content

readLink does not handle undersized buffers well #19137

@squeek502

Description

@squeek502

Zig Version

0.12.0-dev.3090+f5aad4728

Steps to Reproduce and Observed Behavior

const std = @import("std");

test "readLink with undersized buffer" {
    var tmp = std.testing.tmpDir(.{});
    defer tmp.cleanup();

    try tmp.dir.symLink("abc", "symlink", .{});

    var buf: [1]u8 = undefined;
    const target_path = try tmp.dir.readLink("symlink", &buf);
    std.debug.print("{s}\n", .{target_path});
}

On Windows, this hits unreachable:

Test [1/1] test.test.readLink with undersized buffer... thread 13864 panic: reached unreachable code
C:\Users\Ryan\Programming\Zig\zig\lib\std\debug.zig:403:14: 0xc3eb3d in assert (test.exe.obj)
    if (!ok) unreachable; // assertion failure
             ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\unicode.zig:53:11: 0xcb4225 in utf8EncodeImpl__anon_9579 (test.exe.obj)
    assert(out.len >= length);
          ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\unicode.zig:1541:26: 0xcabbd2 in wtf8Encode (test.exe.obj)
    return utf8EncodeImpl(c, out, .can_encode_surrogate_half);
                         ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\unicode.zig:1059:41: 0xc9ba23 in utf16LeToUtf8Impl__anon_9144 (test.exe.obj)
                dest_index += wtf8Encode(codepoint, utf8[dest_index..]) catch |err| switch (err) {
                                        ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\unicode.zig:1712:29: 0xc895d0 in wtf16LeToWtf8 (test.exe.obj)
    return utf16LeToUtf8Impl(wtf8, wtf16le, .can_encode_surrogate_half) catch |err| switch (err) {};
                            ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\os\windows.zig:825:46: 0xc49aef in parseReadlinkPath (test.exe.obj)
    const out_len = std.unicode.wtf16LeToWtf8(out_buffer, win32_namespace_path);
                                             ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\os\windows.zig:798:37: 0xc3b65d in ReadLink (test.exe.obj)
            return parseReadlinkPath(path_buf[offset..][0..len], is_relative, out_buffer);
                                    ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\fs\Dir.zig:1802:35: 0xc3ab24 in readLinkW (test.exe.obj)
    return std.os.windows.ReadLink(self.fd, sub_path_w, buffer);
                                  ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\fs\Dir.zig:1779:30: 0xc32e43 in readLink (test.exe.obj)
        return self.readLinkW(sub_path_w.span(), buffer);
                             ^
C:\Users\Ryan\Programming\Zig\tmp\symlinks\test.zig:10:45: 0xc327b4 in test.readLink with undersized buffer (test.exe.obj)
    const target_path = try tmp.dir.readLink("symlink", &buf);
                                            ^
C:\Users\Ryan\Programming\Zig\zig\lib\compiler\test_runner.zig:158:25: 0xc431e8 in mainTerminal (test.exe.obj)
        if (test_fn.func()) |_| {
                        ^
C:\Users\Ryan\Programming\Zig\zig\lib\compiler\test_runner.zig:35:28: 0xc33368 in main (test.exe.obj)
        return mainTerminal();
                           ^
C:\Users\Ryan\Programming\Zig\zig\lib\std\start.zig:350:53: 0xc330e3 in WinStartup (test.exe.obj)
    std.os.windows.ntdll.RtlExitUserProcess(callMain());
                                                    ^

On Linux, it succeeds with no indication that the full target path was too long for the buffer:

Test [1/1] symlink.test.readLink with undersized buffer... a
All 1 tests passed.

Expected Behavior

readLink should probably fail with NameTooLong or some other relevant error. Or, the behavior around undersized buffers should be documented.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorstandard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions