From be28829ae8d22e1a0373bda116022ee446fb2ed8 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Sun, 30 Jul 2023 14:48:22 +0200 Subject: [PATCH] extmod/vfs_posix: Fix getcwd() on non-root VFS. The unwritten API contract expected of a VFS.getcwd() by mp_vfs_getcwd() is that its return value should be either "" or "/" when the CWD is at the root of the VFS and otherwise start with a slash and not end with a slash. This was not correctly implemented in VfsPosix for instances with a non-empty root - the required leading slash, if any, was cut off because the root length includes a trailing slash. This would result in missing slashes in the middle of the return value of os.getcwd() or in uninitialized garbage from beyond a string's null terminator when the CWD was at the VFS root. Signed-off-by: Christian Walther --- extmod/vfs_posix.c | 9 ++++++++- tests/extmod/vfs_posix_paths.py | 19 +++++++++++++++++++ tests/extmod/vfs_posix_paths.py.exp | 12 +++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index 6df91a2732..e29b47cccd 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -186,7 +186,14 @@ STATIC mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) { if (ret == NULL) { mp_raise_OSError(errno); } - ret += self->root_len; + if (self->root_len > 0) { + ret += self->root_len - 1; + #ifdef _WIN32 + if (*ret == '\\') { + *(char *)ret = '/'; + } + #endif + } return mp_obj_new_str(ret, strlen(ret)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); diff --git a/tests/extmod/vfs_posix_paths.py b/tests/extmod/vfs_posix_paths.py index 8cdad77068..5806a34521 100644 --- a/tests/extmod/vfs_posix_paths.py +++ b/tests/extmod/vfs_posix_paths.py @@ -68,6 +68,25 @@ vfs.rmdir("/subdir") # done with vfs, restore CWD os.chdir(curdir) +# some integration tests with a mounted VFS +os.mount(os.VfsPosix(temp_dir_abs), "/mnt") +os.mkdir("/mnt/dir") +print('chdir("/mnt/dir"):', os.chdir("/mnt/dir")) +print("getcwd():", os.getcwd()) +print('chdir("/mnt"):', os.chdir("/mnt")) +print("getcwd():", os.getcwd()) +print('chdir("/"):', os.chdir("/")) +print("getcwd():", os.getcwd()) +print('chdir("/mnt/dir"):', os.chdir("/mnt/dir")) +print("getcwd():", os.getcwd()) +print('chdir(".."):', os.chdir("..")) +print("getcwd():", os.getcwd()) +os.rmdir("/mnt/dir") +os.umount("/mnt") + +# restore CWD +os.chdir(curdir) + # rmdir os.rmdir(temp_dir) print(temp_dir in os.listdir()) diff --git a/tests/extmod/vfs_posix_paths.py.exp b/tests/extmod/vfs_posix_paths.py.exp index 5828453c92..ecc13222aa 100644 --- a/tests/extmod/vfs_posix_paths.py.exp +++ b/tests/extmod/vfs_posix_paths.py.exp @@ -2,7 +2,7 @@ listdir("/"): ['subdir'] listdir("."): ['subdir'] getcwd() in {"", "/"}: True chdir("subdir"): None -getcwd(): subdir +getcwd(): /subdir mkdir("two"): None listdir("/"): ['subdir'] listdir("/subdir"): ['file.py', 'one', 'two'] @@ -10,4 +10,14 @@ listdir("."): ['file.py', 'one', 'two'] print('hello') hello +chdir("/mnt/dir"): None +getcwd(): /mnt/dir +chdir("/mnt"): None +getcwd(): /mnt +chdir("/"): None +getcwd(): / +chdir("/mnt/dir"): None +getcwd(): /mnt/dir +chdir(".."): None +getcwd(): /mnt False