From ed0474f4d9577c73aea174c832c7d31527de3fd2 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 11 Dec 2024 16:07:31 +0100 Subject: [PATCH 01/10] Fix mkdir a/.. should return EEXIST Before this change `mkdir("a/b/..")` surprisingly makes a directory called `a/b/a`. It should raise EEXIST. --- src/library_fs.js | 10 ++++++-- test/fs/test_fs_mkdir_dotdot.c | 44 ++++++++++++++++++++++++++++++++++ test/test_core.py | 10 ++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 test/fs/test_fs_mkdir_dotdot.c diff --git a/src/library_fs.js b/src/library_fs.js index 68c53ad670bb5..45930661ab571 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -290,6 +290,12 @@ FS.staticInit(); if (errCode) { throw new FS.ErrnoError(errCode); } + if (name === "..") { + return parent.parent; + } + if (name === ".") { + return parent; + } var hash = FS.hashName(parent.id, name); #if CASE_INSENSITIVE_FS name = name.toLowerCase(); @@ -664,8 +670,8 @@ FS.staticInit(); mknod(path, mode, dev) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; - var name = PATH.basename(path); - if (!name || name === '.' || name === '..') { + var name = path.split('/').filter((p) => !!p && (p !== '.')).at(-1); + if (!name) { throw new FS.ErrnoError({{{ cDefs.EINVAL }}}); } var errCode = FS.mayCreate(parent, name); diff --git a/test/fs/test_fs_mkdir_dotdot.c b/test/fs/test_fs_mkdir_dotdot.c new file mode 100644 index 0000000000000..a5f692012a29f --- /dev/null +++ b/test/fs/test_fs_mkdir_dotdot.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(__EMSCRIPTEN__) +#include +#endif + +void makedir(const char *dir) { + int rtn = mkdir(dir, 0777); + assert(rtn == 0); +} + +void changedir(const char *dir) { + int rtn = chdir(dir); + assert(rtn == 0); +} + +void setup() { +#if defined(__EMSCRIPTEN__) && defined(NODEFS) + makedir("working"); + EM_ASM(FS.mount(NODEFS, { root: '.' }, 'working')); + changedir("working"); +#endif +} + +int main() { + setup(); + mkdir("test", 0777); + mkdir("test/a", 0777); + mkdir("test/a/..", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == EEXIST); + mkdir("test/a/.", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == EEXIST); + printf("success\n"); +} + diff --git a/test/test_core.py b/test/test_core.py index d3fff94c5a8ec..3c6de55cacca7 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -5900,6 +5900,16 @@ def test_fs_rename_on_existing(self, args): self.set_setting('FORCE_FILESYSTEM') self.do_runf('fs/test_fs_rename_on_existing.c', 'success', emcc_args=args) + @parameterized({ + '': ([],), + 'nodefs': (['-DNODEFS', '-lnodefs.js'],), + 'noderawfs': (['-sNODERAWFS'],) + }) + def test_fs_mkdir_dotdot(self, args): + if self.get_setting('WASMFS'): + self.set_setting('FORCE_FILESYSTEM') + self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success', emcc_args=args) + def test_sigalrm(self): self.do_runf('test_sigalrm.c', 'Received alarm!') self.set_setting('EXIT_RUNTIME') From f676b41e8f4dc87e373d3b016bf4bc43fb3f5369 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 12 Dec 2024 11:34:02 +0100 Subject: [PATCH 02/10] Fix for old node versions --- src/library_fs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_fs.js b/src/library_fs.js index 45930661ab571..1b701d6f4c796 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -670,7 +670,7 @@ FS.staticInit(); mknod(path, mode, dev) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; - var name = path.split('/').filter((p) => !!p && (p !== '.')).at(-1); + var name = path.split('/').filter((p) => !!p && (p !== '.')).pop(); if (!name) { throw new FS.ErrnoError({{{ cDefs.EINVAL }}}); } From c77a9d50d7adb4bc8799d63f77f27e5ea77d4cb9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 11:43:24 +0100 Subject: [PATCH 03/10] Cleanup --- src/library_fs.js | 3 --- test/fs/test_fs_mkdir_dotdot.c | 20 ++++++++++---------- test/test_core.py | 2 -- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/library_fs.js b/src/library_fs.js index 1b701d6f4c796..c4f1adcdf047d 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -293,9 +293,6 @@ FS.staticInit(); if (name === "..") { return parent.parent; } - if (name === ".") { - return parent; - } var hash = FS.hashName(parent.id, name); #if CASE_INSENSITIVE_FS name = name.toLowerCase(); diff --git a/test/fs/test_fs_mkdir_dotdot.c b/test/fs/test_fs_mkdir_dotdot.c index a5f692012a29f..e7581b74bdd7c 100644 --- a/test/fs/test_fs_mkdir_dotdot.c +++ b/test/fs/test_fs_mkdir_dotdot.c @@ -30,15 +30,15 @@ void setup() { } int main() { - setup(); - mkdir("test", 0777); - mkdir("test/a", 0777); - mkdir("test/a/..", 0777); - printf("error: %s\n", strerror(errno)); - assert(errno == EEXIST); - mkdir("test/a/.", 0777); - printf("error: %s\n", strerror(errno)); - assert(errno == EEXIST); - printf("success\n"); + setup(); + mkdir("test", 0777); + mkdir("test/a", 0777); + mkdir("test/a/..", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == EEXIST); + mkdir("test/a/.", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == EEXIST); + printf("success\n"); } diff --git a/test/test_core.py b/test/test_core.py index 3c6de55cacca7..87d4a22417a2f 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -5906,8 +5906,6 @@ def test_fs_rename_on_existing(self, args): 'noderawfs': (['-sNODERAWFS'],) }) def test_fs_mkdir_dotdot(self, args): - if self.get_setting('WASMFS'): - self.set_setting('FORCE_FILESYSTEM') self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success', emcc_args=args) def test_sigalrm(self): From 1f77f0d84efa2184f427d79c4773af69aa815684 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 19:31:03 +0100 Subject: [PATCH 04/10] Remove normalize() call from basename --- src/library_fs.js | 5 ++++- src/library_path.js | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/library_fs.js b/src/library_fs.js index c4f1adcdf047d..ed8258a41bd3e 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -667,10 +667,13 @@ FS.staticInit(); mknod(path, mode, dev) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; - var name = path.split('/').filter((p) => !!p && (p !== '.')).pop(); + var name = PATH.basename(path); if (!name) { throw new FS.ErrnoError({{{ cDefs.EINVAL }}}); } + if (name === '.' || name === '..') { + throw new FS.ErrnoError({{{ cDefs.EEXIST }}}); + } var errCode = FS.mayCreate(parent, name); if (errCode) { throw new FS.ErrnoError(errCode); diff --git a/src/library_path.js b/src/library_path.js index ab3112503a202..dd367f273eea8 100644 --- a/src/library_path.js +++ b/src/library_path.js @@ -66,7 +66,6 @@ addToLibrary({ basename: (path) => { // EMSCRIPTEN return '/'' for '/', not an empty string if (path === '/') return '/'; - path = PATH.normalize(path); path = path.replace(/\/$/, ""); var lastSlash = path.lastIndexOf('/'); if (lastSlash === -1) return path; From a0a0ed28876f48d7fafcda994dcc5b33eac55a7f Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 19:33:17 +0100 Subject: [PATCH 05/10] fix more --- src/library_fs.js | 6 +++++- test/fs/test_fs_mkdir_dotdot.c | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/library_fs.js b/src/library_fs.js index ed8258a41bd3e..c0c44f6ab0483 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -182,7 +182,7 @@ FS.staticInit(); // limit max consecutive symlinks to 40 (SYMLOOP_MAX). linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) { // split the absolute path - var parts = path.split('/').filter((p) => !!p && (p !== '.')); + var parts = path.split('/').filter((p) => !!p); // start at the root var current = FS.root; @@ -195,6 +195,10 @@ FS.staticInit(); break; } + if (parts[i] === '.') { + continue; + } + if (parts[i] === '..') { current_path = PATH.dirname(current_path); current = current.parent; diff --git a/test/fs/test_fs_mkdir_dotdot.c b/test/fs/test_fs_mkdir_dotdot.c index e7581b74bdd7c..1f4f295497112 100644 --- a/test/fs/test_fs_mkdir_dotdot.c +++ b/test/fs/test_fs_mkdir_dotdot.c @@ -39,6 +39,12 @@ int main() { mkdir("test/a/.", 0777); printf("error: %s\n", strerror(errno)); assert(errno == EEXIST); + mkdir("test/a/b/..", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == ENOENT); + mkdir("test/a/b/.", 0777); + printf("error: %s\n", strerror(errno)); + assert(errno == ENOENT); printf("success\n"); } From 7a2064f5d60c227951733ec160d6e96202e6c4f9 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 19:33:42 +0100 Subject: [PATCH 06/10] Fix typo in comment --- src/library_path.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_path.js b/src/library_path.js index dd367f273eea8..77614a56aba2e 100644 --- a/src/library_path.js +++ b/src/library_path.js @@ -64,7 +64,7 @@ addToLibrary({ return root + dir; }, basename: (path) => { - // EMSCRIPTEN return '/'' for '/', not an empty string + // EMSCRIPTEN return '/' for '/', not an empty string if (path === '/') return '/'; path = path.replace(/\/$/, ""); var lastSlash = path.lastIndexOf('/'); From 301034320cadd8efe0635b31738517febec93bed Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 19:35:25 +0100 Subject: [PATCH 07/10] Cleanup --- src/library_fs.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/library_fs.js b/src/library_fs.js index c0c44f6ab0483..ada447d171c18 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -294,9 +294,6 @@ FS.staticInit(); if (errCode) { throw new FS.ErrnoError(errCode); } - if (name === "..") { - return parent.parent; - } var hash = FS.hashName(parent.id, name); #if CASE_INSENSITIVE_FS name = name.toLowerCase(); From 51c097bd50da657e06186ce0f8a00427f4a82b49 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Mon, 16 Dec 2024 19:40:13 +0100 Subject: [PATCH 08/10] Cleanup test --- test/fs/test_fs_mkdir_dotdot.c | 34 ++++++---------------------------- test/test_core.py | 2 ++ 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/test/fs/test_fs_mkdir_dotdot.c b/test/fs/test_fs_mkdir_dotdot.c index 1f4f295497112..a6504b3e88125 100644 --- a/test/fs/test_fs_mkdir_dotdot.c +++ b/test/fs/test_fs_mkdir_dotdot.c @@ -7,42 +7,20 @@ #include #include #include -#if defined(__EMSCRIPTEN__) -#include -#endif - -void makedir(const char *dir) { - int rtn = mkdir(dir, 0777); - assert(rtn == 0); -} - -void changedir(const char *dir) { - int rtn = chdir(dir); - assert(rtn == 0); -} - -void setup() { -#if defined(__EMSCRIPTEN__) && defined(NODEFS) - makedir("working"); - EM_ASM(FS.mount(NODEFS, { root: '.' }, 'working')); - changedir("working"); -#endif -} int main() { - setup(); - mkdir("test", 0777); - mkdir("test/a", 0777); - mkdir("test/a/..", 0777); + assert(mkdir("test", 0777) == 0); + assert(mkdir("test/a", 0777) == 0); + assert(mkdir("test/a/..", 0777) == -1); printf("error: %s\n", strerror(errno)); assert(errno == EEXIST); - mkdir("test/a/.", 0777); + assert(mkdir("test/a/.", 0777) == -1); printf("error: %s\n", strerror(errno)); assert(errno == EEXIST); - mkdir("test/a/b/..", 0777); + assert(mkdir("test/a/b/..", 0777) == -1); printf("error: %s\n", strerror(errno)); assert(errno == ENOENT); - mkdir("test/a/b/.", 0777); + assert(mkdir("test/a/b/.", 0777) == -1); printf("error: %s\n", strerror(errno)); assert(errno == ENOENT); printf("success\n"); diff --git a/test/test_core.py b/test/test_core.py index 4c78a3cb0fb19..32c405542fb63 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -5908,6 +5908,8 @@ def test_fs_rename_on_existing(self, args): 'noderawfs': (['-sNODERAWFS'],) }) def test_fs_mkdir_dotdot(self, args): + if '-DNODEFS' in args: + self.setup_nodefs_test() self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success', emcc_args=args) def test_sigalrm(self): From f8e2141a4011e33eee74962b5e2061e077f02929 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 18 Dec 2024 11:45:53 +0100 Subject: [PATCH 09/10] Use new decorator --- test/test_core.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/test/test_core.py b/test/test_core.py index c9a44e78529dd..cbdf449ec1d0e 100644 --- a/test/test_core.py +++ b/test/test_core.py @@ -5858,15 +5858,9 @@ def test_fs_rename_on_existing(self): self.set_setting('FORCE_FILESYSTEM') self.do_runf('fs/test_fs_rename_on_existing.c', 'success') - @parameterized({ - '': ([],), - 'nodefs': (['-DNODEFS', '-lnodefs.js'],), - 'noderawfs': (['-sNODERAWFS'],) - }) - def test_fs_mkdir_dotdot(self, args): - if '-DNODEFS' in args: - self.setup_nodefs_test() - self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success', emcc_args=args) + @also_with_nodefs_both + def test_fs_mkdir_dotdot(self): + self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success') def test_sigalrm(self): self.do_runf('test_sigalrm.c', 'Received alarm!') From 431a43225ee6fc36e6e11e4f898aed0e8ed4ddc5 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 18 Dec 2024 16:51:49 +0100 Subject: [PATCH 10/10] Remove extra newline --- test/fs/test_fs_mkdir_dotdot.c | 1 - 1 file changed, 1 deletion(-) diff --git a/test/fs/test_fs_mkdir_dotdot.c b/test/fs/test_fs_mkdir_dotdot.c index a6504b3e88125..4bda788dd452a 100644 --- a/test/fs/test_fs_mkdir_dotdot.c +++ b/test/fs/test_fs_mkdir_dotdot.c @@ -25,4 +25,3 @@ int main() { assert(errno == ENOENT); printf("success\n"); } -