mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-02 15:33:39 +02:00
gfileutils: Correctly reset start value when canonicalising paths
If a path starts with more than two slashes, the `start` value was previously incorrect: 1. As per the `g_path_skip_root()` call, `start` was set to point to after the final initial slash. For a path with three initial slashes, this is the character after the third slash. 2. The canonicalisation loop to find the first dir separator sets `output` to point to the character after the first slash (and it overwrites the first slash to be `G_DIR_SEPARATOR`). 3. At this point, with a string `///usr`, `output` points to the second `/`; and `start` points to the `u`. This is incorrect, as `start` should point to the starting character for output, as per the original call to `g_path_skip_root()`. 4. For paths which subsequently include a `..`, this results in the `output > start` check in the `..` loop below not skipping all the characters of a preceding path component, which is then caught by the `G_IS_DIR_SEPARATOR (output[-1])` assertion. Fix this by resetting `start` to `output` after finding the final slash to keep in the output, but before starting the main parsing loop. Relatedly, split `start` into two variables: `after_root` and `output_start`, since the variable actually has two roles in the two parts of the function. Includes a test. This commit is heavily based on suggestions by Sebastian Wilhemi and Sebastian Dröge. Signed-off-by: Philip Withnall <pwithnall@endlessos.org> oss-fuzz#41563
This commit is contained in:
@@ -1063,6 +1063,7 @@ test_paths (void)
|
||||
{ "/", "./", "/" },
|
||||
{ "/", "/.", "/" },
|
||||
{ "/", "/./", "/" },
|
||||
{ "/", "///usr/../usr", "/usr" },
|
||||
#else
|
||||
{ "/etc", "../usr/share", "\\usr\\share" },
|
||||
{ "/", "/foo/bar", "\\foo\\bar" },
|
||||
@@ -1090,6 +1091,7 @@ test_paths (void)
|
||||
{ "/", "./", "/" },
|
||||
{ "/", "/.", "/" },
|
||||
{ "/", "/./", "/" },
|
||||
{ "/", "///usr/../usr", "/usr" },
|
||||
|
||||
{ "\\etc", "..\\usr\\share", "\\usr\\share" },
|
||||
{ "\\", "\\foo\\bar", "\\foo\\bar" },
|
||||
@@ -1117,6 +1119,7 @@ test_paths (void)
|
||||
{ "\\", ".\\", "\\" },
|
||||
{ "\\", "\\.", "\\" },
|
||||
{ "\\", "\\.\\", "\\" },
|
||||
{ "\\", "\\\\\\usr\\..\\usr", "\\usr" },
|
||||
#endif
|
||||
};
|
||||
const guint n_canonicalize_filename_checks = G_N_ELEMENTS (canonicalize_filename_checks);
|
||||
|
Reference in New Issue
Block a user