diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_path_util.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/path_util.c | 26 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_path_util_test.cc | 11 |
3 files changed, 33 insertions, 6 deletions
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 6d411b51f85..1b723ab038d 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -364,6 +364,8 @@ bool BLI_path_make_safe(char *path) ATTR_NONNULL(1); * * Replaces path with the path of its parent directory, returning true if * it was able to find a parent directory within the path. + * + * On success, the resulting path will always have a trailing slash. */ bool BLI_path_parent_dir(char *path) ATTR_NONNULL(); /** diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index df18689c74c..f46c2e65395 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -630,14 +630,28 @@ bool BLI_path_parent_dir(char *path) char tmp[FILE_MAX + 4]; BLI_path_join(tmp, sizeof(tmp), path, parent_dir); - BLI_path_normalize(NULL, tmp); /* does all the work of normalizing the path for us */ - - if (!BLI_path_extension_check(tmp, parent_dir)) { - strcpy(path, tmp); /* We assume the parent directory is always shorter. */ - return true; + /* Does all the work of normalizing the path for us. + * + * NOTE(@campbellbarton): While it's possible strip text after the second last slash, + * this would have to be clever and skip cases like "/./" & multiple slashes. + * Since this ends up solving some of the same problems as #BLI_path_normalize, + * call this function instead of attempting to handle them separately. */ + BLI_path_normalize(NULL, tmp); + + /* Use #BLI_path_name_at_index instead of checking if the strings ends with `parent_dir` + * to ensure the logic isn't confused by: + * - Directory names that happen to end with `..`. + * - When `path` is empty, the contents will be `../` + * which would cause checking for a tailing `/../` fail. + * Extracting the span of the final directory avoids both these issues. */ + int tail_ofs = 0, tail_len = 0; + if (BLI_path_name_at_index(tmp, -1, &tail_ofs, &tail_len) && (tail_len == 2) && + (memcmp(&tmp[tail_ofs], "..", 2) == 0)) { + return false; } - return false; + strcpy(path, tmp); /* We assume the parent directory is always shorter. */ + return true; } bool BLI_path_parent_dir_until_exists(char *dir) diff --git a/source/blender/blenlib/tests/BLI_path_util_test.cc b/source/blender/blenlib/tests/BLI_path_util_test.cc index 51db376e03f..93922b41b23 100644 --- a/source/blender/blenlib/tests/BLI_path_util_test.cc +++ b/source/blender/blenlib/tests/BLI_path_util_test.cc @@ -75,6 +75,17 @@ TEST(path_util, ParentDir) PARENT_DIR("/a/b", "/a/"); PARENT_DIR("/a", "/"); PARENT_DIR("/", "/"); + PARENT_DIR("", ""); + + /* Ensure trailing dots aren't confused with parent path. */ + PARENT_DIR("/.../.../.../", "/.../.../"); + PARENT_DIR("/.../.../...", "/.../.../"); + + PARENT_DIR("/a../b../c../", "/a../b../"); + PARENT_DIR("/a../b../c..", "/a../b../"); + + PARENT_DIR("/a./b./c./", "/a./b./"); + PARENT_DIR("/a./b./c.", "/a./b./"); # undef PARENT_DIR } |