Zig Version
0.14.0-dev.653+91c17979f
Steps to Reproduce and Observed Behavior
conststd=@import("std");
test"fstatat on a symlink with SYMLINK_NOFOLLOW" {
vartmp=std.testing.tmpDir(.{});
defertmp.cleanup();
consttestfile=trytmp.dir.createFile("testfile", .{});
testfile.close();
trytmp.dir.symLink("testfile", "testsymlink", .{});
conststat=trystd.posix.fstatat(tmp.dir.fd, "testsymlink", std.posix.AT.SYMLINK_NOFOLLOW);
std.testing.expect(stat.mode & std.posix.S.IFLNK==std.posix.S.IFLNK) catch|err| {
std.debug.print("stat.mode={X}\n", .{stat.mode});
returnerr;
};
}This test passes normally and when targeting wasm32-wasi and not linking libc:
$ zig test stat-symlink-test.zig -target wasm32-wasi -femit-bin=stat-symlink-test.wasm --test-no-exec
$ wasmtime --dir=. stat-symlink-test.wasmAll 1 tests passed.
But fails when linking libc (meaning wasi-libc):
$ wasmtime --dir=. stat-symlink-test-libc.wasmstat.mode=80001/1 stat-symlink-test.test.fstatat on a symlink with SYMLINK_NOFOLLOW...FAIL (TestUnexpectedResult)Unable to dump stack trace: not implemented for Wasm0 passed; 0 skipped; 1 failed.
(that mode is IFREG aka a file)
This is not a problem with the parameters being passed to fstatat: I confirmed that the AT_SYMLINK_NOFOLLOW is being passed to the fstatat_sym call here:
| switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) { |
But strace shows that the NOFOLLOW flag is being dropped when going through wasmtime (the openat2 call should have O_NOFOLLOW, which it does when not linking wasi-libc):
openat2(13, "testsymlink", {flags=O_RDONLY|O_CLOEXEC|O_PATH, resolve=RESOLVE_NO_MAGICLINKS|RESOLVE_BENEATH}, 24) = 11
statx(11, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_ALL|STATX_MNT_ID, stx_attributes=0, stx_mode=S_IFREG|0664, stx_size=0, ...}) = 0
close(11) = 0
My first thought was that this is a wasi-libc/wasmtime bug, similar to #20747, but I have been unable to find a reproduction when building an intended-to-be-equivalent C version via wasi-sdk. Here's the program I'm trying (I'm using wasi-sdk 23.0 and wasmtime 23.0.1):
#include<sys/stat.h>#include<sys/types.h>#include<fcntl.h>#include<unistd.h>#include<stdio.h>intmain() {
mkdirat(AT_FDCWD, "testdir", 0777);
intdirfd=openat(AT_FDCWD, "testdir", O_RDONLY|O_DIRECTORY);
intfd=openat(dirfd, "testfile", O_RDONLY|O_CREAT);
close(fd);
symlinkat("testfile", dirfd, "testsymlink");
structstatst;
fstatat(dirfd, "testsymlink", &st, AT_SYMLINK_NOFOLLOW);
printf("%X\n", st.st_mode);
if ((st.st_mode&S_IFLNK) ==0) return1;
return0;
}Built with:
$ WASI_SDK=/home/ryan/Downloads/wasi-sdk-23.0-x86_64-linux
$ $WASI_SDK/bin/clang --sysroot=$WASI_SDK/share/wasi-sysroot stat-symlink.c -o stat-symlink-sdk.wasm
And run with:
$ wasmtime --dir=. stat-symlink-sdk.wasmA000
(0xA000 is S_IFLNK aka symlink)
Expected Behavior
The test to pass when linking wasi-libc
Zig Version
0.14.0-dev.653+91c17979f
Steps to Reproduce and Observed Behavior
This test passes normally and when targeting
wasm32-wasiand not linking libc:But fails when linking libc (meaning
wasi-libc):(that mode is
IFREGaka a file)This is not a problem with the parameters being passed to
fstatat: I confirmed that theAT_SYMLINK_NOFOLLOWis being passed to thefstatat_symcall here:zig/lib/std/posix.zig
Line 4382 in 059856a
But
straceshows that theNOFOLLOWflag is being dropped when going throughwasmtime(theopenat2call should haveO_NOFOLLOW, which it does when not linkingwasi-libc):My first thought was that this is a
wasi-libc/wasmtimebug, similar to #20747, but I have been unable to find a reproduction when building an intended-to-be-equivalent C version viawasi-sdk. Here's the program I'm trying (I'm usingwasi-sdk 23.0andwasmtime 23.0.1):Built with:
And run with:
(0xA000 is S_IFLNK aka symlink)
Expected Behavior
The test to pass when linking
wasi-libc