Skip to content

Commit

Permalink
Fix mkdir("a/b/..") should return EEXIST (#23136)
Browse files Browse the repository at this point in the history
Before this change `mkdir("a/b/..")` surprisingly makes a directory
called `a/b/a`. It should raise EEXIST.
  • Loading branch information
hoodmane authored Dec 18, 2024
1 parent 978488b commit c26d805
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/library_fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -195,6 +195,10 @@ FS.staticInit();
break;
}

if (parts[i] === '.') {
continue;
}

if (parts[i] === '..') {
current_path = PATH.dirname(current_path);
current = current.parent;
Expand Down Expand Up @@ -665,9 +669,12 @@ FS.staticInit();
var lookup = FS.lookupPath(path, { parent: true });
var parent = lookup.node;
var name = PATH.basename(path);
if (!name || name === '.' || name === '..') {
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);
Expand Down
27 changes: 27 additions & 0 deletions test/fs/test_fs_mkdir_dotdot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

int main() {
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);
assert(mkdir("test/a/.", 0777) == -1);
printf("error: %s\n", strerror(errno));
assert(errno == EEXIST);
assert(mkdir("test/a/b/..", 0777) == -1);
printf("error: %s\n", strerror(errno));
assert(errno == ENOENT);
assert(mkdir("test/a/b/.", 0777) == -1);
printf("error: %s\n", strerror(errno));
assert(errno == ENOENT);
printf("success\n");
}
4 changes: 4 additions & 0 deletions test/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -5858,6 +5858,10 @@ def test_fs_rename_on_existing(self):
self.set_setting('FORCE_FILESYSTEM')
self.do_runf('fs/test_fs_rename_on_existing.c', 'success')

@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!')
self.do_runf('test_sigalrm.c', 'Received alarm!', emcc_args=['-sEXIT_RUNTIME'])
Expand Down

0 comments on commit c26d805

Please sign in to comment.