Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-11-01 14:02:08 +0300
committerCampbell Barton <campbell@blender.org>2022-11-01 23:21:10 +0300
commitcc6f41f8a53f7f0392afa59e6da8ebc3849fc03c (patch)
treee25c65ab46eb06847f32d93ee8cf283f441ab4bc
parent12f4ac170658f82ce85d96873cfb32ec786136ec (diff)
Fix BLI_path_parent_dir failing on paths ending with ".."
The check for BLI_path_normalize having succeeded only checked for a trailing "../" which isn't correct. This caused going up a directory in the file selector to do nothing on directories ending with "..". This also caused an empty path to expand into "../" because BLI_path_extension_check didn't account for this case. Resolve using BLI_path_name_at_index which extracts the last component of the path without having to match the the surrounding slashes.
-rw-r--r--source/blender/blenlib/BLI_path_util.h2
-rw-r--r--source/blender/blenlib/intern/path_util.c26
-rw-r--r--source/blender/blenlib/tests/BLI_path_util_test.cc11
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
}