Skip to content

[FS] Fix resolvePath handling of .. up from fs mountpoint #23990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/lib/libfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,12 @@ FS.staticInit();

if (parts[i] === '..') {
current_path = PATH.dirname(current_path);
current = current.parent;
if (FS.isRoot(current)) {
path = current_path + '/' + parts.slice(i + 1).join('/');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the current node is the root node can we just assume current path is / here and do path = '/' + parts.slice(i + 1).join('/')

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because FS.isRoot() returns true if it's the root of a mount. So in the test, because we mounted NODEFS at /working, FS.isRoot() will return true when processing the .. in the path "/working/../other".

continue linkloop;
} else {
current = current.parent;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If parts[i] === '..' and the current not is the FS root shouldn't we be failing? (Since there is no parent of the root?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not consistent with linux's stat. If a .. is seen at the root, it is ignored:

$ stat /../lib
  File: /../lib -> usr/lib
  Size: 7         	Blocks: 0          IO Block: 4096   symbolic link

}
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8219
8232
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors1.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19929
19993
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8207
8221
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_ctors2.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19907
19971
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9217
9231
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23666
23730
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8165
8177
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_except_wasm.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19821
19885
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8165
8177
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19821
19885
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8234
8245
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_lto.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20003
20067
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9255
9268
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_mangle.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
23780
23844
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8219
8232
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_cxx_noexcept.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
19929
19993
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.gzsize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7528
7542
2 changes: 1 addition & 1 deletion test/other/codesize/test_codesize_files_js_fs.jssize
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18487
18551
15 changes: 15 additions & 0 deletions test/other/test_resolve_mountpoint_parent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <emscripten.h>
#include "assert.h"

int main(int argc, char **argv) {
EM_ASM({
FS.mkdir('/working');
FS.mkdir('/other');
FS.mount(NODEFS, { root: '.' }, '/working');
});
struct stat statBuf;
assert(stat("/working/../other", &statBuf) == 0);
}
Empty file.
5 changes: 5 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -8190,6 +8190,11 @@ def test_realpath_2(self):
create_file('Folder/testfile.txt', '')
self.do_other_test('test_realpath_2.c', emcc_args=['--embed-file', 'testfile.txt', '--embed-file', 'Folder'])

@requires_node
@also_with_wasmfs
def test_resolve_mountpoint_parent(self):
self.do_other_test('test_resolve_mountpoint_parent.c', emcc_args=['-sFORCE_FILESYSTEM', '-lnodefs.js'])

@with_env_modify({'EMCC_LOGGING': '0'}) # this test assumes no emcc output
def test_no_warnings(self):
# build once before to make sure system libs etc. exist
Expand Down