emscripten-core / emscripten

Emscripten: An LLVM-to-WebAssembly Compiler
Other
25.62k stars 3.28k forks source link

Windows file paths causes `ENOENT` errors starting with Emscripten v3.1.8 #17360

Closed merceyz closed 1 year ago

merceyz commented 2 years ago

Starting in Emscripten v3.1.8, calling fopen with absolute Windows file paths causes ENOENT errors. The error comes from ___syscall_openat where it tries to open the following path:

C:\\absolute\\path\\to\\cwd/C:\\absolute\\path\\to\\file;

Reproduction:

Build the following C code with the provided build command

// read.c
#include <stdio.h>
#include <stdlib.h>

void openfile(char *filename)
{
  FILE *fptr = fopen(filename, "r");
  if (fptr == NULL)
  {
    printf("Error!");
    exit(1);
  }
}

and run the following Node.js script.

// test.js
const createModule = require(`./build`);

createModule().then((mod) => {
    mod.cwrap(`openfile`, `void`, [`string`])(__filename);
});

Version of emscripten/emsdk:

emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.8 (3ff7eff373d31d8c0179895165462019221f192e)
clang version 15.0.0 (https://github.com/llvm/llvm-project 80ec0ebfdc5692a58e0832125f2c6a991df9d63f)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin

Full link command and output with -v appended:

$ docker run --rm -it -v "$(pwd):/src" emscripten/emsdk:3.1.8 emcc \
  -o ./build.js \
  -s WASM=1 \
  -s EXPORTED_FUNCTIONS="[\"_openfile\"]" \
  -s EXPORTED_RUNTIME_METHODS='["cwrap"]' \
  -s ENVIRONMENT=node \
  -s MODULARIZE=1 \
  -s NODERAWFS=1 \
  -s EXPORT_NAME="createModule" \
  -v \
  ./read.c
 "/emsdk/upstream/bin/clang" -target wasm32-unknown-emscripten -DEMSCRIPTEN -D__EMSCRIPTEN_major__=3 -D__EMSCRIPTEN_minor__=1 -D__EMSCRIPTEN_tiny__=8 -fignore-exceptions -fvisibility=default -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/emsdk/upstream/emscripten/cache/sysroot -Xclang -iwithsysroot/include/compat -v ./read.c -c -o /tmp/emscripten_temp_kdqujioh/read_0.o
clang version 15.0.0 (https://github.com/llvm/llvm-project 80ec0ebfdc5692a58e0832125f2c6a991df9d63f)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /emsdk/upstream/bin
 (in-process)
 "/emsdk/upstream/bin/clang-15" -cc1 -triple wasm32-unknown-emscripten -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name read.c -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -mllvm -treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v -fcoverage-compilation-dir=/src -resource-dir /emsdk/upstream/lib/clang/15.0.0 -D EMSCRIPTEN -D __EMSCRIPTEN_major__=3 -D __EMSCRIPTEN_minor__=1 -D
__EMSCRIPTEN_tiny__=8 -isysroot /emsdk/upstream/emscripten/cache/sysroot -internal-isystem /emsdk/upstream/lib/clang/15.0.0/include -internal-isystem /emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten -internal-isystem /emsdk/upstream/emscripten/cache/sysroot/include -Werror=implicit-function-declaration -fdebug-compilation-dir=/src -ferror-limit 19 -fvisibility default -fgnuc-version=4.2.1 -fignore-exceptions -fcolor-diagnostics -iwithsysroot/include/SDL -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /tmp/emscripten_temp_kdqujioh/read_0.o -x c ./read.c
clang -cc1 version 15.0.0 based upon LLVM 15.0.0git default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/emsdk/upstream/emscripten/cache/sysroot/include/wasm32-emscripten"
#include "..." search starts here:
#include <...> search starts here:
 /emsdk/upstream/emscripten/cache/sysroot/include/SDL
 /emsdk/upstream/emscripten/cache/sysroot/include/compat
 /emsdk/upstream/lib/clang/15.0.0/include
 /emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
 "/emsdk/upstream/bin/wasm-ld" -o ./build.wasm /tmp/emscripten_temp_kdqujioh/read_0.o -L/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten -lGL -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --import-undefined --strip-debug --export-if-defined=openfile --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__stdio_exit --export=emscripten_stack_get_end
--export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_init --export=stackSave --export=stackRestore --export=stackAlloc --export=__wasm_call_ctors --export=__errno_location --export-table -z stack-size=5242880 --initial-memory=16777216 --no-entry --max-memory=16777216 --global-base=1024
 "/emsdk/upstream/bin/wasm-emscripten-finalize" --dyncalls-i64 ./build.wasm -o ./build.wasm --detect-features
 "/emsdk/node/14.18.2_64bit/bin/node" /emsdk/upstream/emscripten/src/compiler.js /tmp/tmpffzp_sty.json
 "/emsdk/upstream/bin/llvm-objcopy" ./build.wasm ./build.wasm --remove-section=.debug* --remove-section=producers
kleisauke commented 2 years ago

Probably this was introduced by commit 1a0b77c572adbaa6e207aae0912b9cc27b573d80, which removes the #define SYS_open __syscall_open definition causing __syscall_openat to be called instead. Some more context: https://github.com/emscripten-core/emscripten/pull/16296#issuecomment-1079979886.

(I've a patch lying around here that fixes this, but it didn't fully pass the test suite the last time I tried to upstream it).