Skip to content

Commit ed0474f

Browse files
committed
Fix mkdir a/.. should return EEXIST
Before this change `mkdir("a/b/..")` surprisingly makes a directory called `a/b/a`. It should raise EEXIST.
1 parent 1171ada commit ed0474f

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

src/library_fs.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,12 @@ FS.staticInit();
290290
if (errCode) {
291291
throw new FS.ErrnoError(errCode);
292292
}
293+
if (name === "..") {
294+
return parent.parent;
295+
}
296+
if (name === ".") {
297+
return parent;
298+
}
293299
var hash = FS.hashName(parent.id, name);
294300
#if CASE_INSENSITIVE_FS
295301
name = name.toLowerCase();
@@ -664,8 +670,8 @@ FS.staticInit();
664670
mknod(path, mode, dev) {
665671
var lookup = FS.lookupPath(path, { parent: true });
666672
var parent = lookup.node;
667-
var name = PATH.basename(path);
668-
if (!name || name === '.' || name === '..') {
673+
var name = path.split('/').filter((p) => !!p && (p !== '.')).at(-1);
674+
if (!name) {
669675
throw new FS.ErrnoError({{{ cDefs.EINVAL }}});
670676
}
671677
var errCode = FS.mayCreate(parent, name);

test/fs/test_fs_mkdir_dotdot.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <sys/stat.h>
2+
#include <sys/types.h>
3+
#include <unistd.h>
4+
#include <sys/stat.h>
5+
#include <stdio.h>
6+
#include <fcntl.h>
7+
#include <errno.h>
8+
#include <string.h>
9+
#include <assert.h>
10+
#if defined(__EMSCRIPTEN__)
11+
#include <emscripten.h>
12+
#endif
13+
14+
void makedir(const char *dir) {
15+
int rtn = mkdir(dir, 0777);
16+
assert(rtn == 0);
17+
}
18+
19+
void changedir(const char *dir) {
20+
int rtn = chdir(dir);
21+
assert(rtn == 0);
22+
}
23+
24+
void setup() {
25+
#if defined(__EMSCRIPTEN__) && defined(NODEFS)
26+
makedir("working");
27+
EM_ASM(FS.mount(NODEFS, { root: '.' }, 'working'));
28+
changedir("working");
29+
#endif
30+
}
31+
32+
int main() {
33+
setup();
34+
mkdir("test", 0777);
35+
mkdir("test/a", 0777);
36+
mkdir("test/a/..", 0777);
37+
printf("error: %s\n", strerror(errno));
38+
assert(errno == EEXIST);
39+
mkdir("test/a/.", 0777);
40+
printf("error: %s\n", strerror(errno));
41+
assert(errno == EEXIST);
42+
printf("success\n");
43+
}
44+

test/test_core.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5900,6 +5900,16 @@ def test_fs_rename_on_existing(self, args):
59005900
self.set_setting('FORCE_FILESYSTEM')
59015901
self.do_runf('fs/test_fs_rename_on_existing.c', 'success', emcc_args=args)
59025902

5903+
@parameterized({
5904+
'': ([],),
5905+
'nodefs': (['-DNODEFS', '-lnodefs.js'],),
5906+
'noderawfs': (['-sNODERAWFS'],)
5907+
})
5908+
def test_fs_mkdir_dotdot(self, args):
5909+
if self.get_setting('WASMFS'):
5910+
self.set_setting('FORCE_FILESYSTEM')
5911+
self.do_runf('fs/test_fs_mkdir_dotdot.c', 'success', emcc_args=args)
5912+
59035913
def test_sigalrm(self):
59045914
self.do_runf('test_sigalrm.c', 'Received alarm!')
59055915
self.set_setting('EXIT_RUNTIME')

0 commit comments

Comments
 (0)