mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
libfetchers: Remove badGitRefRegex and use libgit2 for reference validation
Fixes usage of `#` symbol in the reference name. This also seems to identify several deficiencies in the libgit2 refname validation code wrt to DEL symbol and a singular `@` symbol [1]. [1]: https://git-scm.com/docs/git-check-ref-format#_description
This commit is contained in:
parent
0b7f7e4b03
commit
e8e9376a7b
10 changed files with 154 additions and 19 deletions
|
|
@ -93,8 +93,11 @@ Hash toHash(const git_oid & oid)
|
|||
|
||||
static void initLibGit2()
|
||||
{
|
||||
if (git_libgit2_init() < 0)
|
||||
throw Error("initialising libgit2: %s", git_error_last()->message);
|
||||
static std::once_flag initialized;
|
||||
std::call_once(initialized, []() {
|
||||
if (git_libgit2_init() < 0)
|
||||
throw Error("initialising libgit2: %s", git_error_last()->message);
|
||||
});
|
||||
}
|
||||
|
||||
git_oid hashToOID(const Hash & hash)
|
||||
|
|
@ -1308,4 +1311,63 @@ GitRepo::WorkdirInfo GitRepo::getCachedWorkdirInfo(const std::filesystem::path &
|
|||
return workdirInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the git reference is valid and normalizes slash '/' sequences.
|
||||
*
|
||||
* Accepts shorthand references (one-level refnames are allowed).
|
||||
*/
|
||||
bool isValidRefNameAllowNormalizations(const std::string & refName)
|
||||
{
|
||||
/* Unfortunately libgit2 doesn't expose the limit in headers, but its internal
|
||||
limit is also 1024. */
|
||||
std::array<char, 1024> normalizedRefBuffer;
|
||||
|
||||
/* It would be nice to have a better API like git_reference_name_is_valid, but
|
||||
* with GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND flag. libgit2 uses it internally
|
||||
* but doesn't expose it in public headers [1].
|
||||
* [1]:
|
||||
* https://github.com/libgit2/libgit2/blob/9d5f1bacc23594c2ba324c8f0d41b88bf0e9ef04/src/libgit2/refs.c#L1362-L1365
|
||||
*/
|
||||
|
||||
auto res = git_reference_normalize_name(
|
||||
normalizedRefBuffer.data(),
|
||||
normalizedRefBuffer.size(),
|
||||
refName.c_str(),
|
||||
GIT_REFERENCE_FORMAT_ALLOW_ONELEVEL | GIT_REFERENCE_FORMAT_REFSPEC_SHORTHAND);
|
||||
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
bool isLegalRefName(const std::string & refName)
|
||||
{
|
||||
initLibGit2();
|
||||
|
||||
/* Since `git_reference_normalize_name` is the best API libgit2 has for verifying
|
||||
* reference names with shorthands (see comment in normalizeRefName), we need to
|
||||
* ensure that exceptions to the validity checks imposed by normalization [1] are checked
|
||||
* explicitly.
|
||||
* [1]: https://git-scm.com/docs/git-check-ref-format#Documentation/git-check-ref-format.txt---normalize
|
||||
*/
|
||||
|
||||
/* Check for cases that don't get rejected by libgit2.
|
||||
* FIXME: libgit2 should reject this. */
|
||||
if (refName == "@")
|
||||
return false;
|
||||
|
||||
/* Leading slashes and consecutive slashes are stripped during normalizatiton. */
|
||||
if (refName.starts_with('/') || refName.find("//") != refName.npos)
|
||||
return false;
|
||||
|
||||
/* Refer to libgit2. */
|
||||
if (!isValidRefNameAllowNormalizations(refName))
|
||||
return false;
|
||||
|
||||
/* libgit2 doesn't barf on DEL symbol.
|
||||
* FIXME: libgit2 should reject this. */
|
||||
if (refName.find('\177') != refName.npos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue