ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.89k stars 2.55k forks source link

std.fmt.bufPrint panics when arguments alias, not mentioned in docs #15850

Open jayschwa opened 1 year ago

jayschwa commented 1 year ago

Zig Version

0.11.0-dev.3298+5744ceedb

Steps to Reproduce and Observed Behavior

const std = @import("std");
const bufPrint = std.fmt.bufPrint;

test "bufPrint arguments alias" {
    var buf: [10]u8 = undefined;
    const foo = try bufPrint(&buf, "{s}", .{"foo"});
    const foobar = try bufPrint(&buf, "{s}{s}", .{ foo, "bar" });
    _ = foobar;
}
$ zig test test.zig
Test [1/1] test.bufPrint aliased arguments... thread 19632 panic: @memcpy arguments alias
/snap/zig/7524/lib/std/io/fixed_buffer_stream.zig:70:57: 0x2112bf in write (test)
            @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]);
                                                        ^
/snap/zig/7524/lib/std/io/writer.zig:17:27: 0x21bc4b in write (test)
            return writeFn(self.context, bytes);
                          ^
/snap/zig/7524/lib/std/io/writer.zig:23:40: 0x212dc2 in writeAll (test)
                index += try self.write(bytes[index..]);
                                       ^
/snap/zig/7524/lib/std/fmt.zig:1055:28: 0x2127f8 in formatBuf__anon_3582 (test)
        try writer.writeAll(buf);
                           ^
/snap/zig/7524/lib/std/fmt.zig:656:45: 0x210208 in formatType__anon_1453 (test)
                            return formatBuf(value, options, writer);
                                            ^
/snap/zig/7524/lib/std/fmt.zig:184:23: 0x2100c6 in format__anon_1440 (test)
        try formatType(
                      ^
/snap/zig/7524/lib/std/fmt.zig:1995:15: 0x20f54c in bufPrint__anon_1144 (test)
    try format(fbs.writer(), fmt, args);
              ^
/home/jayschwa/Desktop/test.zig:7:32: 0x20f267 in test.bufPrint aliased arguments (test)
    const foobar = try bufPrint(&buf, "{s}{s}", .{ foo, "bar" });
                               ^

Expected Behavior

This concatenative use of bufPrint worked not long ago (within the last month, I think). If the new behavior is working as intended, then documentation for the function probably ought to mention it.

yozachar commented 1 year ago

Another example:

const std = @import("std");
const fmt = std.fmt;

/// start here
pub fn main() !void {
    const home_dir: [:0]const u8 = std.os.getenv("HOME") orelse "~/";
    var max_path_buffer: [std.fs.MAX_PATH_BYTES]u8 = [_]u8{0} ** std.fs.MAX_PATH_BYTES; // Type inference is 'unknown'
    // how do I annotate alternate types like [:0]const u8 | []u8 ?
    const cache_dir = std.os.getenv("XDG_CACHE_HOME") orelse try fmt.bufPrint(&max_path_buffer, "{s}/.cache", .{home_dir});
    max_path_buffer = [_]u8{0} ** std.fs.MAX_PATH_BYTES; // is repeat necessary?
    const themepak_cache_dir: []u8 = try fmt.bufPrint(&max_path_buffer, "{s}/themepak", .{cache_dir});
    // max_path_buffer = [_]u8{0} ** std.fs.MAX_PATH_BYTES;
    // // No Error, but 'themepak_cache_dir' is blank when the above line is uncommented, I wonder why? 👇
    // std.debug.print("\n{s} : {d} : {s}\n", .{ cache_dir, @sizeOf(@TypeOf(max_path_buffer)), themepak_cache_dir });
    max_path_buffer = [_]u8{0} ** std.fs.MAX_PATH_BYTES; // better than writing to undefined?
    const themepak_repo_dir: []u8 = try fmt.bufPrint(&max_path_buffer, "{s}/repo", .{themepak_cache_dir});
    // 👇 ERROR HERE 👇 
    std.debug.print("\n{d} : {s} : {s} : {s}\n", .{ @sizeOf(@TypeOf(max_path_buffer)), cache_dir, themepak_cache_dir, themepak_repo_dir });
}

Console:

$ zig build run
thread 14394 panic: @memcpy arguments alias
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/fixed_buffer_stream.zig:70:57: 0x260342 in write (themepak)
            @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]);
                                                        ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/writer.zig:17:27: 0x25056b in write (themepak)
            return writeFn(self.context, bytes);
                          ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/writer.zig:23:40: 0x223404 in writeAll (themepak)
                index += try self.write(bytes[index..]);
                                       ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:1047:28: 0x24fe4c in formatBuf__anon_7370 (themepak)
        try writer.writeAll(buf);
                           ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:656:45: 0x22382e in formatType__anon_4262 (themepak)
                            return formatBuf(value, options, writer);
                                            ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:184:23: 0x223746 in format__anon_4251 (themepak)
        try formatType(
                      ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:1996:15: 0x22073c in bufPrint__anon_3291 (themepak)
    try format(fbs.writer(), fmt, args);
              ^
/home/user/Documents/workspace/github/themepak/src/main.zig:59:53: 0x220037 in main (themepak)
    const themepak_repo_dir: []u8 = try fmt.bufPrint(&max_path_buffer, "{s}/repo", .{themepak_cache_dir});
                                                    ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/start.zig:574:37: 0x21fc3e in posixCallMainAndExit (themepak)
            const result = root.main() catch |err| {
                                    ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/start.zig:243:5: 0x21f721 in _start (themepak)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)
run themepak: error: the following command terminated unexpectedly:
/home/user/Documents/workspace/github/themepak/zig-out/bin/themepak 
Build Summary: 3/5 steps succeeded; 1 failed (disable with --summary none)
run transitive failure
└─ run themepak failure
error: the following build command failed with exit code 1:
/home/user/Documents/workspace/github/themepak/zig-cache/o/a0d8a311e0d341f44ca99205bb4f181b/build /home/user/.local/share/rtx/installs/zig/0.11.0/zig /home/user/Documents/workspace/github/themepak /home/user/Documents/workspace/github/themepak/zig-cache /home/user/.cache/zig run

When running the (only) file individually:

hread 14555 panic: @memcpy arguments alias
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/fixed_buffer_stream.zig:70:57: 0x260342 in write (main)
            @memcpy(self.buffer[self.pos..][0..n], bytes[0..n]);
                                                        ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/writer.zig:17:27: 0x25056b in write (main)
            return writeFn(self.context, bytes);
                          ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/io/writer.zig:23:40: 0x223404 in writeAll (main)
                index += try self.write(bytes[index..]);
                                       ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:1047:28: 0x24fe4c in formatBuf__anon_7370 (main)
        try writer.writeAll(buf);
                           ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:656:45: 0x22382e in formatType__anon_4262 (main)
                            return formatBuf(value, options, writer);
                                            ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:184:23: 0x223746 in format__anon_4251 (main)
        try formatType(
                      ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/fmt.zig:1996:15: 0x22073c in bufPrint__anon_3291 (main)
    try format(fbs.writer(), fmt, args);
              ^
/home/user/Documents/workspace/github/themepak/src/main.zig:59:53: 0x220037 in main (main)
    const themepak_repo_dir: []u8 = try fmt.bufPrint(&max_path_buffer, "{s}/repo", .{themepak_cache_dir});
                                                    ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/start.zig:574:37: 0x21fc3e in posixCallMainAndExit (main)
            const result = root.main() catch |err| {
                                    ^
/home/user/.local/share/rtx/installs/zig/0.11.0/lib/std/start.zig:243:5: 0x21f721 in _start (main)
    asm volatile (switch (native_arch) {
    ^
???:?:?: 0x0 in ??? (???)
zsh: IOT instruction (core dumped)  zig run src/main.zig
$ zig version         
0.11.0
Pyrolistical commented 5 months ago

still an issue in latest 0.14.0-dev.32+4aa15440c