Working directory path validation - #5823
Conversation
|
Thinking through this, I think that a rough validation plan is:
|
1729a42 to
6c5217b
Compare
805e9ca to
92d8e69
Compare
Move the utf8 functions into a proper namespace `git_utf8` instead of being in the namespaceless `git__` function group. Update them to have out-params first and use `char *` instead of `uint8_t *` to match our API treating strings as `char *` (even if they truly contain `uchar`s inside).
Introduce a function to determine the number of Unicode characters in a given UTF-8 string.
If we want to validate more and different types of paths, the name `git_path_validate` makes that easier and more expressive. We can add, for example, `git_path_validate_foo` while the current name makes that less ergonomic.
f271ee5 to
fc47848
Compare
37a7b94 to
5f516ee
Compare
Introduce `git_path_validate_filesystem` which validates (absolute) on-disk paths and `git_path_validate_workdir` to perform validations on (absolute) working directory paths. These functions are useful as there may be system limitations on on-disk paths, particularly on Windows (for example, enforcing MAX_PATH). For working directory paths, these limitations may be per-repository, based on the `core.longpaths` configuration setting.
There was no test ensuring that we validate `.git` paths. We do, but let's add a test to make sure that we never regress this.
Add a simple accessor for workdir paths to get an absolute on-disk path given a repository and a relative path within it. This is useful to avoid copy-pasta `git_buf_joinpath` and to ensure that we validate working directory paths while honoring `core.longpaths` settings.
We're not necessarily checking out into the working directory. We could be checking out into an arbitrary location. Ensure that when we are writing conflict data that we do it in the checkout target.
Ensure that we are validating working directory paths before we try to write to them.
Use `git_repository_workdir_path` to generate workdir paths since it will validate the length.
The new git_repository_workdir_path function does error checking on working directory inputs on Windows; use it to construct paths within working directories.
We should allow attribute files - inside working directories - to have names longer than MAX_PATH when core.longpaths is set. `git_attr_path__init` takes a repository to validate the path with.
Supply the repository for the filesystem and workdir iterators - for workdir iterators, this is non-null and we can lookup the core.longpaths configuration option. (For regular filesystem iterators, this is NULL, so core.longpaths does not apply.)
Validate that working directory paths honor `core.longpaths` where appropriate. Paths to the submodule gitdirs must always honor the operating system length restrictions; `core.longpaths` does not affect gitdir paths.
Worktree paths need to fix within MAX_PATH always, regardless of `core.longpaths` setting.
Let `git_path_find_dir` simply take a `git_buf` that contains a directory or a file, instead of trying to both join a path AND then deal with prettifying it or its basename. This allows consumers to join paths themselves (and apply any necessary rules - like fitting within MAX_PATH).
On Windows, we need to enforce MAX_PATH for loose references and their reflogs. Ensure that any path - including the lock file - would fit within the 260 character maximum. We do not honor core.longpaths for loose reference files or reflogs. core.longpaths only applies to paths in the working directory.
Ensure that a repository's path (at initialization or open time) is valid. On Windows systems, this means that the longest known path beneath the repository will fit within MAX_PATH: this is a lock file for a loose object within the repository itself. Other paths, like a very long loose reference, may fail to be opened after the repository is opened. These variable length paths will be checked when they are accessed themselves. This new functionality is done at open to prevent needlessly checking every file in the gitdir (eg, `MERGE_HEAD`) for its length when we could instead check once at repository open time.
5f516ee to
c15ed35
Compare
|
Going to go ahead and merge this to land #5347 |
Add
git_path_validate_ondiskwhich validates... well, on-disk paths. These paths could be working directory paths or things inside the.gitdirectory.The goal is to limit Windows path lengths to
MAX_PATHin general. For working directory paths whencore.longpathsis set, we will allow arbitrary length paths.We do not consult
core.longpathsfor things outside the working directory and will restrict any paths inside.gitto be less thanMAX_PATH. Note that this is not in keeping with Git for Windows, which does no validation and will fail silently when trying to construct a directory where a critical component of the.gitdirectory would be longer thanMAX_PATH. 🤷This converts several path writers to use this, but not all. In particular, submodules and worktrees will require some more careful thought. In addition, I'll perform a more extensive audit before converting this from a draft to a real PR. 🙃