Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libgit2 for openSUSE:Factory checked 
in at 2022-04-16 00:12:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libgit2 (Old)
 and      /work/SRC/openSUSE:Factory/.libgit2.new.1941 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libgit2"

Sat Apr 16 00:12:48 2022 rev:49 rq:969974 version:1.4.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/libgit2/libgit2.changes  2022-03-23 
20:15:34.826367821 +0100
+++ /work/SRC/openSUSE:Factory/.libgit2.new.1941/libgit2.changes        
2022-04-16 00:12:51.297537396 +0200
@@ -1,0 +2,8 @@
+Wed Apr 13 17:53:54 UTC 2022 - Andreas Stieger <andreas.stie...@gmx.de>
+
+- update to 1.4.3:
+  * compatibility with git's changes for CVE-2022-24765 boo#1187234
+  * several correctness fixes where invalid input can lead to a
+    crash and denial of service
+
+-------------------------------------------------------------------

Old:
----
  libgit2-1.4.2.tar.gz

New:
----
  libgit2-1.4.3.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libgit2.spec ++++++
--- /var/tmp/diff_new_pack.wFD5D1/_old  2022-04-16 00:12:51.797538064 +0200
+++ /var/tmp/diff_new_pack.wFD5D1/_new  2022-04-16 00:12:51.801538069 +0200
@@ -19,7 +19,7 @@
 
 %define sover 1_4
 Name:           libgit2
-Version:        1.4.2
+Version:        1.4.3
 Release:        0
 Summary:        C git library
 License:        GPL-2.0-only WITH GCC-exception-2.0

++++++ libgit2-1.4.2.tar.gz -> libgit2-1.4.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/CMakeLists.txt 
new/libgit2-1.4.3/CMakeLists.txt
--- old/libgit2-1.4.2/CMakeLists.txt    2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/CMakeLists.txt    2022-04-12 22:17:07.000000000 +0200
@@ -3,7 +3,7 @@
 
 cmake_minimum_required(VERSION 3.5.1)
 
-project(libgit2 VERSION "1.4.0" LANGUAGES C)
+project(libgit2 VERSION "1.4.3" LANGUAGES C)
 
 # Add find modules to the path
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/docs/changelog.md 
new/libgit2-1.4.3/docs/changelog.md
--- old/libgit2-1.4.2/docs/changelog.md 2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/docs/changelog.md 2022-04-12 22:17:07.000000000 +0200
@@ -1,3 +1,23 @@
+v1.4.3
+------
+
+???? This is a security release to provide compatibility with git's changes to 
address [CVE 
2022-24765](https://github.blog/2022-04-12-git-security-vulnerability-announced/).
+
+**libgit2 is not directly affected** by this vulnerability, because libgit2 
does not directly invoke any executable. But we are providing these changes as 
a security release for any users that use libgit2 for repository discovery and 
then _also_ use git on that repository. In this release, we will now validate 
that the user opening the repository is the same user that owns the on-disk 
repository. This is to match git's behavior.
+
+In addition, we are providing several correctness fixes where invalid input 
can lead to a crash. These may prevent possible denial of service attacks. At 
this time there are not known exploits to these issues.
+
+Full list of changes:
+
+* Validate repository directory ownership (v1.4) by @ethomson in 
https://github.com/libgit2/libgit2/pull/6267
+* midx: Fix an undefined behavior (left-shift signed overflow) by @lhchavez in 
https://github.com/libgit2/libgit2/pull/6260
+* fetch: support OID refspec without dst by @ethomson in 
https://github.com/libgit2/libgit2/pull/6251
+* Fix crash when regenerating a patch with unquoted spaces in filename by 
@jorio in https://github.com/libgit2/libgit2/pull/6244
+
+All users of the v1.4 release line are recommended to upgrade.
+
+**Full Changelog**: https://github.com/libgit2/libgit2/compare/v1.4.2...v1.4.3
+
 v1.4.2
 ------
 
Binary files 
old/libgit2-1.4.2/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e 
and 
new/libgit2-1.4.3/fuzzers/corpora/midx/666a779eed16847c6930a71c0547a34e52db409e 
differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/include/git2/common.h 
new/libgit2-1.4.3/include/git2/common.h
--- old/libgit2-1.4.2/include/git2/common.h     2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/include/git2/common.h     2022-04-12 22:17:07.000000000 
+0200
@@ -214,7 +214,9 @@
        GIT_OPT_SET_ODB_PACKED_PRIORITY,
        GIT_OPT_SET_ODB_LOOSE_PRIORITY,
        GIT_OPT_GET_EXTENSIONS,
-       GIT_OPT_SET_EXTENSIONS
+       GIT_OPT_SET_EXTENSIONS,
+       GIT_OPT_GET_OWNER_VALIDATION,
+       GIT_OPT_SET_OWNER_VALIDATION
 } git_libgit2_opt_t;
 
 /**
@@ -452,6 +454,14 @@
  *      > to support repositories with the `noop` extension but does want
  *      > to support repositories with the `newext` extension.
  *
+ *   opts(GIT_OPT_GET_OWNER_VALIDATION, int *enabled)
+ *      > Gets the owner validation setting for repository
+ *      > directories.
+ *
+ *   opts(GIT_OPT_SET_OWNER_VALIDATION, int enabled)
+ *      > Set that repository directories should be owned by the current
+ *      > user. The default is to validate ownership.
+ *
  * @param option Option key
  * @param ... value to set the option
  * @return 0 on success, <0 on failure
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/include/git2/errors.h 
new/libgit2-1.4.3/include/git2/errors.h
--- old/libgit2-1.4.2/include/git2/errors.h     2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/include/git2/errors.h     2022-04-12 22:17:07.000000000 
+0200
@@ -57,7 +57,8 @@
        GIT_RETRY           = -32,      /**< Internal only */
        GIT_EMISMATCH       = -33,      /**< Hashsum mismatch in object */
        GIT_EINDEXDIRTY     = -34,      /**< Unsaved changes in the index would 
be overwritten */
-       GIT_EAPPLYFAIL      = -35       /**< Patch application failed */
+       GIT_EAPPLYFAIL      = -35,      /**< Patch application failed */
+       GIT_EOWNER          = -36       /**< The object is not owned by the 
current user */
 } git_error_code;
 
 /**
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/include/git2/version.h 
new/libgit2-1.4.3/include/git2/version.h
--- old/libgit2-1.4.2/include/git2/version.h    2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/include/git2/version.h    2022-04-12 22:17:07.000000000 
+0200
@@ -7,10 +7,10 @@
 #ifndef INCLUDE_git_version_h__
 #define INCLUDE_git_version_h__
 
-#define LIBGIT2_VERSION "1.4.2"
+#define LIBGIT2_VERSION "1.4.3"
 #define LIBGIT2_VER_MAJOR 1
 #define LIBGIT2_VER_MINOR 4
-#define LIBGIT2_VER_REVISION 2
+#define LIBGIT2_VER_REVISION 3
 #define LIBGIT2_VER_PATCH 0
 
 #define LIBGIT2_SOVERSION "1.4"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/package.json 
new/libgit2-1.4.3/package.json
--- old/libgit2-1.4.2/package.json      2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/package.json      2022-04-12 22:17:07.000000000 +0200
@@ -1,6 +1,6 @@
 {
   "name": "libgit2",
-  "version": "1.4.0",
+  "version": "1.4.3",
   "repo": "https://github.com/libgit2/libgit2";,
   "description": " A cross-platform, linkable library implementation of Git 
that you can use in your application.",
   "install": "mkdir build && cd build && cmake .. && cmake --build ."
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/config.c 
new/libgit2-1.4.3/src/config.c
--- old/libgit2-1.4.2/src/config.c      2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/config.c      2022-04-12 22:17:07.000000000 +0200
@@ -1170,14 +1170,18 @@
 
 int git_config__find_programdata(git_str *path)
 {
-       int ret;
+       bool is_safe;
 
-       ret = git_sysdir_find_programdata_file(path, 
GIT_CONFIG_FILENAME_PROGRAMDATA);
+       if (git_sysdir_find_programdata_file(path, 
GIT_CONFIG_FILENAME_PROGRAMDATA) < 0 ||
+           git_fs_path_owner_is_system_or_current_user(&is_safe, path->ptr) < 
0)
+               return -1;
 
-       if (ret != GIT_OK)
-               return ret;
+       if (!is_safe) {
+               git_error_set(GIT_ERROR_CONFIG, "programdata path has invalid 
ownership");
+               return -1;
+       }
 
-       return git_fs_path_validate_system_file_ownership(path->ptr);
+       return 0;
 }
 
 int git_config__global_location(git_str *buf)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/diff_print.c 
new/libgit2-1.4.3/src/diff_print.c
--- old/libgit2-1.4.2/src/diff_print.c  2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/diff_print.c  2022-04-12 22:17:07.000000000 +0200
@@ -316,6 +316,11 @@
 static int diff_delta_format_path(
        git_str *out, const char *prefix, const char *filename)
 {
+       if (!filename) {
+               /* don't prefix "/dev/null" */
+               return git_str_puts(out, "/dev/null");
+       }
+
        if (git_str_joinpath(out, prefix, filename) < 0)
                return -1;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/fetch.c 
new/libgit2-1.4.3/src/fetch.c
--- old/libgit2-1.4.2/src/fetch.c       2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/fetch.c       2022-04-12 22:17:07.000000000 +0200
@@ -76,8 +76,11 @@
        GIT_ERROR_CHECK_ALLOC(oid_head);
 
        git_oid_fromstr(&oid_head->oid, spec->src);
-       oid_head->name = git__strdup(spec->dst);
-       GIT_ERROR_CHECK_ALLOC(oid_head->name);
+
+       if (spec->dst) {
+               oid_head->name = git__strdup(spec->dst);
+               GIT_ERROR_CHECK_ALLOC(oid_head->name);
+       }
 
        if (git_vector_insert(&remote->local_heads, oid_head) < 0 ||
            git_vector_insert(&remote->refs, oid_head) < 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/fs_path.c 
new/libgit2-1.4.3/src/fs_path.c
--- old/libgit2-1.4.2/src/fs_path.c     2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/fs_path.c     2022-04-12 22:17:07.000000000 +0200
@@ -1779,82 +1779,241 @@
        return supported;
 }
 
-int git_fs_path_validate_system_file_ownership(const char *path)
+static git_fs_path__mock_owner_t mock_owner = GIT_FS_PATH_MOCK_OWNER_NONE;
+
+void git_fs_path__set_owner(git_fs_path__mock_owner_t owner)
+{
+       mock_owner = owner;
+}
+
+#ifdef GIT_WIN32
+static PSID *sid_dup(PSID sid)
+{
+       DWORD len;
+       PSID dup;
+
+       len = GetLengthSid(sid);
+
+       if ((dup = git__malloc(len)) == NULL)
+               return NULL;
+
+       if (!CopySid(len, dup, sid)) {
+               git_error_set(GIT_ERROR_OS, "could not duplicate sid");
+               git__free(dup);
+               return NULL;
+       }
+
+       return dup;
+}
+
+static int current_user_sid(PSID *out)
 {
-#ifndef GIT_WIN32
-       GIT_UNUSED(path);
-       return GIT_OK;
-#else
-       git_win32_path buf;
-       PSID owner_sid;
-       PSECURITY_DESCRIPTOR descriptor = NULL;
-       HANDLE token;
        TOKEN_USER *info = NULL;
-       DWORD err, len;
-       int ret;
+       HANDLE token = NULL;
+       DWORD len = 0;
+       int error = -1;
 
-       if (git_win32_path_from_utf8(buf, path) < 0)
-               return -1;
+       if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
+               git_error_set(GIT_ERROR_OS, "could not lookup process 
information");
+               goto done;
+       }
 
-       err = GetNamedSecurityInfoW(buf, SE_FILE_OBJECT,
-                                   OWNER_SECURITY_INFORMATION |
-                                           DACL_SECURITY_INFORMATION,
-                                   &owner_sid, NULL, NULL, NULL, &descriptor);
+       if (GetTokenInformation(token, TokenUser, NULL, 0, &len) ||
+               GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+               git_error_set(GIT_ERROR_OS, "could not lookup token metadata");
+               goto done;
+       }
 
-       if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
-               ret = GIT_ENOTFOUND;
-               goto cleanup;
+       info = git__malloc(len);
+       GIT_ERROR_CHECK_ALLOC(info);
+
+       if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
+               git_error_set(GIT_ERROR_OS, "could not lookup current user");
+               goto done;
        }
 
-       if (err != ERROR_SUCCESS) {
+       if ((*out = sid_dup(info->User.Sid)))
+               error = 0;
+
+done:
+       if (token)
+               CloseHandle(token);
+
+       git__free(info);
+       return error;
+}
+
+static int file_owner_sid(PSID *out, const char *path)
+{
+       git_win32_path path_w32;
+       PSECURITY_DESCRIPTOR descriptor = NULL;
+       PSID owner_sid;
+       DWORD ret;
+       int error = -1;
+
+       if (git_win32_path_from_utf8(path_w32, path) < 0)
+               return -1;
+
+       ret = GetNamedSecurityInfoW(path_w32, SE_FILE_OBJECT,
+               OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+               &owner_sid, NULL, NULL, NULL, &descriptor);
+
+       if (ret == ERROR_FILE_NOT_FOUND || ret == ERROR_PATH_NOT_FOUND)
+               error = GIT_ENOTFOUND;
+       else if (ret != ERROR_SUCCESS)
                git_error_set(GIT_ERROR_OS, "failed to get security 
information");
-               ret = GIT_ERROR;
-               goto cleanup;
+       else if (!IsValidSid(owner_sid))
+               git_error_set(GIT_ERROR_OS, "file owner is not valid");
+       else if ((*out = sid_dup(owner_sid)))
+               error = 0;
+
+       if (descriptor)
+               LocalFree(descriptor);
+
+       return error;
+}
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path)
+{
+       PSID owner_sid = NULL, user_sid = NULL;
+       int error = -1;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
        }
 
-       if (!IsValidSid(owner_sid)) {
-               git_error_set(GIT_ERROR_INVALID, "programdata configuration 
file owner is unknown");
-               ret = GIT_ERROR;
-               goto cleanup;
+       if ((error = file_owner_sid(&owner_sid, path)) < 0 ||
+           (error = current_user_sid(&user_sid)) < 0)
+               goto done;
+
+       *out = EqualSid(owner_sid, user_sid);
+       error = 0;
+
+done:
+       git__free(owner_sid);
+       git__free(user_sid);
+       return error;
+}
+
+int git_fs_path_owner_is_system(bool *out, const char *path)
+{
+       PSID owner_sid;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+               return 0;
        }
 
+       if (file_owner_sid(&owner_sid, path) < 0)
+               return -1;
+
+       *out = IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
+              IsWellKnownSid(owner_sid, WinLocalSystemSid);
+
+       git__free(owner_sid);
+       return 0;
+}
+
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
+{
+       PSID owner_sid = NULL, user_sid = NULL;
+       int error = -1;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
+                       mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       if (file_owner_sid(&owner_sid, path) < 0)
+               goto done;
+
        if (IsWellKnownSid(owner_sid, WinBuiltinAdministratorsSid) ||
            IsWellKnownSid(owner_sid, WinLocalSystemSid)) {
-               ret = GIT_OK;
-               goto cleanup;
+               *out = 1;
+               error = 0;
+               goto done;
+       }
+
+       if (current_user_sid(&user_sid) < 0)
+               goto done;
+
+       *out = EqualSid(owner_sid, user_sid);
+       error = 0;
+
+done:
+       git__free(owner_sid);
+       git__free(user_sid);
+       return error;
+}
+
+#else
+
+static int fs_path_owner_is(bool *out, const char *path, uid_t *uids, size_t 
uids_len)
+{
+       struct stat st;
+       size_t i;
+
+       *out = false;
+
+       if (p_lstat(path, &st) != 0) {
+               if (errno == ENOENT)
+                       return GIT_ENOTFOUND;
+
+               git_error_set(GIT_ERROR_OS, "could not stat '%s'", path);
+               return -1;
        }
 
-       /* Obtain current user's SID */
-       if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) &&
-           !GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
-               info = git__malloc(len);
-               GIT_ERROR_CHECK_ALLOC(info);
-               if (!GetTokenInformation(token, TokenUser, info, len, &len)) {
-                       git__free(info);
-                       info = NULL;
+       for (i = 0; i < uids_len; i++) {
+               if (uids[i] == st.st_uid) {
+                       *out = true;
+                       break;
                }
        }
 
-       /*
-        * If the file is owned by the same account that is running the current
-        * process, it's okay to read from that file.
-        */
-       if (info && EqualSid(owner_sid, info->User.Sid))
-               ret = GIT_OK;
-       else {
-               git_error_set(GIT_ERROR_INVALID, "programdata configuration 
file owner is not valid");
-               ret = GIT_ERROR;
+       return 0;
+}
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path)
+{
+       uid_t userid = geteuid();
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
        }
-       git__free(info);
 
-cleanup:
-       if (descriptor)
-               LocalFree(descriptor);
+       return fs_path_owner_is(out, path, &userid, 1);
+}
 
-       return ret;
-#endif
+int git_fs_path_owner_is_system(bool *out, const char *path)
+{
+       uid_t userid = 0;
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+               return 0;
+       }
+
+       return fs_path_owner_is(out, path, &userid, 1);
 }
 
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path)
+{
+       uid_t userids[2] = { geteuid(), 0 };
+
+       if (mock_owner) {
+               *out = (mock_owner == GIT_FS_PATH_MOCK_OWNER_SYSTEM ||
+                       mock_owner == GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+               return 0;
+       }
+
+       return fs_path_owner_is(out, path, userids, 2);
+}
+
+#endif
+
 int git_fs_path_find_executable(git_str *fullpath, const char *executable)
 {
 #ifdef GIT_WIN32
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/fs_path.h 
new/libgit2-1.4.3/src/fs_path.h
--- old/libgit2-1.4.2/src/fs_path.h     2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/fs_path.h     2022-04-12 22:17:07.000000000 +0200
@@ -731,17 +731,37 @@
 
 bool git_fs_path_supports_symlinks(const char *dir);
 
+typedef enum {
+       GIT_FS_PATH_MOCK_OWNER_NONE = 0, /* do filesystem lookups as normal */
+       GIT_FS_PATH_MOCK_OWNER_SYSTEM = 1,
+       GIT_FS_PATH_MOCK_OWNER_CURRENT_USER = 2,
+       GIT_FS_PATH_MOCK_OWNER_OTHER = 3
+} git_fs_path__mock_owner_t;
+
+/**
+ * Sets the mock ownership for files; subsequent calls to
+ * `git_fs_path_owner_is_*` functions will return this data until cleared
+ * with `GIT_FS_PATH_MOCK_OWNER_NONE`.
+ */
+void git_fs_path__set_owner(git_fs_path__mock_owner_t owner);
+
+/**
+ * Verify that the file in question is owned by an administrator or system
+ * account.
+ */
+int git_fs_path_owner_is_system(bool *out, const char *path);
+
+/**
+ * Verify that the file in question is owned by the current user;
+ */
+
+int git_fs_path_owner_is_current_user(bool *out, const char *path);
+
 /**
- * Validate a system file's ownership
- *
  * Verify that the file in question is owned by an administrator or system
- * account, or at least by the current user.
- *
- * This function returns 0 if successful. If the file is not owned by any of
- * these, or any other if there have been problems determining the file
- * ownership, it returns -1.
+ * account _or_ the current user;
  */
-int git_fs_path_validate_system_file_ownership(const char *path);
+int git_fs_path_owner_is_system_or_current_user(bool *out, const char *path);
 
 /**
  * Search the current PATH for the given executable, returning the full
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/libgit2.c 
new/libgit2-1.4.3/src/libgit2.c
--- old/libgit2-1.4.2/src/libgit2.c     2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/libgit2.c     2022-04-12 22:17:07.000000000 +0200
@@ -401,6 +401,14 @@
                }
                break;
 
+       case GIT_OPT_GET_OWNER_VALIDATION:
+               *(va_arg(ap, int *)) = git_repository__validate_ownership;
+               break;
+
+       case GIT_OPT_SET_OWNER_VALIDATION:
+               git_repository__validate_ownership = (va_arg(ap, int) != 0);
+               break;
+
        default:
                git_error_set(GIT_ERROR_INVALID, "invalid option key");
                error = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/midx.c new/libgit2-1.4.3/src/midx.c
--- old/libgit2-1.4.2/src/midx.c        2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/midx.c        2022-04-12 22:17:07.000000000 +0200
@@ -225,8 +225,13 @@
        chunk_hdr = data + sizeof(struct git_midx_header);
        last_chunk = NULL;
        for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
-               chunk_offset = ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 4)))) 
<< 32 |
-                               ((off64_t)ntohl(*((uint32_t *)(chunk_hdr + 
8))));
+               uint32_t chunk_id = ntohl(*((uint32_t *)(chunk_hdr + 0)));
+               uint64_t high_offset = ((uint64_t)ntohl(*((uint32_t 
*)(chunk_hdr + 4)))) & 0xffffffffu;
+               uint64_t low_offset = ((uint64_t)ntohl(*((uint32_t *)(chunk_hdr 
+ 8)))) & 0xffffffffu;
+
+               if (high_offset >= INT32_MAX)
+                       return midx_error("chunk offset out of range");
+               chunk_offset = (off64_t)(high_offset << 32 | low_offset);
                if (chunk_offset < last_chunk_offset)
                        return midx_error("chunks are non-monotonic");
                if (chunk_offset >= trailer_offset)
@@ -235,7 +240,7 @@
                        last_chunk->length = (size_t)(chunk_offset - 
last_chunk_offset);
                last_chunk_offset = chunk_offset;
 
-               switch (ntohl(*((uint32_t *)(chunk_hdr + 0)))) {
+               switch (chunk_id) {
                case MIDX_PACKFILE_NAMES_ID:
                        chunk_packfile_names.offset = last_chunk_offset;
                        last_chunk = &chunk_packfile_names;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/remote.c 
new/libgit2-1.4.3/src/remote.c
--- old/libgit2-1.4.2/src/remote.c      2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/remote.c      2022-04-12 22:17:07.000000000 +0200
@@ -1895,8 +1895,11 @@
        if (git_oid__is_hexstr(spec->src)) {
                git_oid id;
 
-               if ((error = git_oid_fromstr(&id, spec->src)) < 0 ||
-                   (error = update_ref(remote, spec->dst, &id, log_message, 
callbacks)) < 0)
+               if ((error = git_oid_fromstr(&id, spec->src)) < 0)
+                       goto on_error;
+
+               if (spec->dst &&
+                    (error = update_ref(remote, spec->dst, &id, log_message, 
callbacks)) < 0)
                        goto on_error;
 
                git_oid_cpy(&oid_head.oid, &id);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/repository.c 
new/libgit2-1.4.3/src/repository.c
--- old/libgit2-1.4.2/src/repository.c  2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/repository.c  2022-04-12 22:17:07.000000000 +0200
@@ -39,6 +39,7 @@
 # include "win32/w32_util.h"
 #endif
 
+bool git_repository__validate_ownership = true;
 bool git_repository__fsync_gitdir = false;
 
 static const struct {
@@ -65,6 +66,7 @@
 
 static int check_repositoryformatversion(int *version, git_config *config);
 static int check_extensions(git_config *config, int version);
+static int load_global_config(git_config **config);
 
 #define GIT_COMMONDIR_FILE "commondir"
 #define GIT_GITDIR_FILE "gitdir"
@@ -483,6 +485,63 @@
        return error;
 }
 
+typedef struct {
+       const char *repo_path;
+       git_str tmp;
+       bool is_safe;
+} validate_ownership_data;
+
+static int validate_ownership_cb(const git_config_entry *entry, void *payload)
+{
+       validate_ownership_data *data = payload;
+
+       if (strcmp(entry->value, "") == 0)
+               data->is_safe = false;
+
+       if (git_fs_path_prettify_dir(&data->tmp, entry->value, NULL) == 0 &&
+           strcmp(data->tmp.ptr, data->repo_path) == 0)
+               data->is_safe = true;
+
+       return 0;
+}
+
+static int validate_ownership(const char *repo_path)
+{
+       git_config *config = NULL;
+       validate_ownership_data data = { repo_path, GIT_STR_INIT, false };
+       bool is_safe;
+       int error;
+
+       if ((error = git_fs_path_owner_is_current_user(&is_safe, repo_path)) < 
0) {
+               if (error == GIT_ENOTFOUND)
+                       error = 0;
+
+               goto done;
+       }
+
+       if (is_safe) {
+               error = 0;
+               goto done;
+       }
+
+       if (load_global_config(&config) == 0) {
+               error = git_config_get_multivar_foreach(config, 
"safe.directory", NULL, validate_ownership_cb, &data);
+
+               if (!error && data.is_safe)
+                       goto done;
+       }
+
+       git_error_set(GIT_ERROR_CONFIG,
+               "repository path '%s' is not owned by current user",
+               repo_path);
+       error = GIT_EOWNER;
+
+done:
+       git_config_free(config);
+       git_str_dispose(&data.tmp);
+       return error;
+}
+
 static int find_repo(
        git_str *gitdir_path,
        git_str *workdir_path,
@@ -856,6 +915,7 @@
                gitlink = GIT_STR_INIT, commondir = GIT_STR_INIT;
        git_repository *repo = NULL;
        git_config *config = NULL;
+       const char *validation_path;
        int version = 0;
 
        if (flags & GIT_REPOSITORY_OPEN_FROM_ENV)
@@ -904,16 +964,24 @@
        if ((error = check_extensions(config, version)) < 0)
                goto cleanup;
 
-       if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0)
+       if ((flags & GIT_REPOSITORY_OPEN_BARE) != 0) {
                repo->is_bare = 1;
-       else {
-
+       } else {
                if (config &&
                    ((error = load_config_data(repo, config)) < 0 ||
                     (error = load_workdir(repo, config, &workdir)) < 0))
                        goto cleanup;
        }
 
+       /*
+        * Ensure that the git directory is owned by the current user.
+        */
+       validation_path = repo->is_bare ? repo->gitdir : repo->workdir;
+
+       if (git_repository__validate_ownership &&
+           (error = validate_ownership(validation_path)) < 0)
+               goto cleanup;
+
 cleanup:
        git_str_dispose(&gitdir);
        git_str_dispose(&workdir);
@@ -1606,13 +1674,40 @@
        return is_insensitive;
 }
 
-static bool are_symlinks_supported(const char *wd_path)
+/*
+ * Return a configuration object with only the global and system
+ * configurations; no repository-level configuration.
+ */
+static int load_global_config(git_config **config)
 {
-       git_config *config = NULL;
        git_str global_buf = GIT_STR_INIT;
        git_str xdg_buf = GIT_STR_INIT;
        git_str system_buf = GIT_STR_INIT;
        git_str programdata_buf = GIT_STR_INIT;
+       int error;
+
+       git_config__find_global(&global_buf);
+       git_config__find_xdg(&xdg_buf);
+       git_config__find_system(&system_buf);
+       git_config__find_programdata(&programdata_buf);
+
+       error = load_config(config, NULL,
+                           path_unless_empty(&global_buf),
+                           path_unless_empty(&xdg_buf),
+                           path_unless_empty(&system_buf),
+                           path_unless_empty(&programdata_buf));
+
+       git_str_dispose(&global_buf);
+       git_str_dispose(&xdg_buf);
+       git_str_dispose(&system_buf);
+       git_str_dispose(&programdata_buf);
+
+       return error;
+}
+
+static bool are_symlinks_supported(const char *wd_path)
+{
+       git_config *config = NULL;
        int symlinks = 0;
 
        /*
@@ -1623,19 +1718,9 @@
         * _not_ set, then we do not test or enable symlink support.
         */
 #ifdef GIT_WIN32
-       git_config__find_global(&global_buf);
-       git_config__find_xdg(&xdg_buf);
-       git_config__find_system(&system_buf);
-       git_config__find_programdata(&programdata_buf);
-
-       if (load_config(&config, NULL,
-           path_unless_empty(&global_buf),
-           path_unless_empty(&xdg_buf),
-           path_unless_empty(&system_buf),
-           path_unless_empty(&programdata_buf)) < 0)
-               goto done;
-
-       if (git_config_get_bool(&symlinks, config, "core.symlinks") < 0 || 
!symlinks)
+       if (load_global_config(&config) < 0 ||
+           git_config_get_bool(&symlinks, config, "core.symlinks") < 0 ||
+           !symlinks)
                goto done;
 #endif
 
@@ -1643,10 +1728,6 @@
                goto done;
 
 done:
-       git_str_dispose(&global_buf);
-       git_str_dispose(&xdg_buf);
-       git_str_dispose(&system_buf);
-       git_str_dispose(&programdata_buf);
        git_config_free(config);
        return symlinks != 0;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/src/repository.h 
new/libgit2-1.4.3/src/repository.h
--- old/libgit2-1.4.2/src/repository.h  2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/src/repository.h  2022-04-12 22:17:07.000000000 +0200
@@ -34,6 +34,7 @@
 #define GIT_DIR_SHORTNAME "GIT~1"
 
 extern bool git_repository__fsync_gitdir;
+extern bool git_repository__validate_ownership;
 
 /** Cvar cache identifiers */
 typedef enum {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/clar_libgit2.c 
new/libgit2-1.4.3/tests/clar_libgit2.c
--- old/libgit2-1.4.2/tests/clar_libgit2.c      2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/clar_libgit2.c      2022-04-12 22:17:07.000000000 
+0200
@@ -599,6 +599,11 @@
        git_str_dispose(&path);
 }
 
+void cl_sandbox_disable_ownership_validation(void)
+{
+       git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 0);
+}
+
 #ifdef GIT_WIN32
 bool cl_sandbox_supports_8dot3(void)
 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/clar_libgit2.h 
new/libgit2-1.4.3/tests/clar_libgit2.h
--- old/libgit2-1.4.2/tests/clar_libgit2.h      2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/clar_libgit2.h      2022-04-12 22:17:07.000000000 
+0200
@@ -222,6 +222,7 @@
 void cl_fake_home_cleanup(void *);
 
 void cl_sandbox_set_search_path_defaults(void);
+void cl_sandbox_disable_ownership_validation(void);
 
 #ifdef GIT_WIN32
 # define cl_msleep(x) Sleep(x)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/core/path.c 
new/libgit2-1.4.3/tests/core/path.c
--- old/libgit2-1.4.2/tests/core/path.c 2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/tests/core/path.c 2022-04-12 22:17:07.000000000 +0200
@@ -737,3 +737,28 @@
        git_str_dispose(&sandbox_path);
        git__free(orig_path);
 }
+
+void test_core_path__validate_current_user_ownership(void)
+{
+       bool is_cur;
+
+       cl_must_pass(p_mkdir("testdir", 0777));
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testdir"));
+       cl_assert_equal_i(is_cur, 1);
+
+       cl_git_rewritefile("testfile", "This is a test file.");
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testfile"));
+       cl_assert_equal_i(is_cur, 1);
+
+#ifdef GIT_WIN32
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "C:\\"));
+       cl_assert_equal_i(is_cur, 0);
+
+       cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, 
"c:\\path\\does\\not\\exist"));
+#else
+       cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "/"));
+       cl_assert_equal_i(is_cur, 0);
+
+       cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, 
"/path/does/not/exist"));
+#endif
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/diff/parse.c 
new/libgit2-1.4.3/tests/diff/parse.c
--- old/libgit2-1.4.2/tests/diff/parse.c        2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/diff/parse.c        2022-04-12 22:17:07.000000000 
+0200
@@ -431,6 +431,32 @@
        git_diff_free(diff);
 }
 
+void test_diff_parse__new_file_with_space_and_regenerate_patch(void)
+{
+       const char *content = PATCH_ORIGINAL_NEW_FILE_WITH_SPACE;
+       git_diff *diff = NULL;
+       git_buf buf = GIT_BUF_INIT;
+
+       cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+       cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+       git_buf_dispose(&buf);
+       git_diff_free(diff);
+}
+
+void test_diff_parse__delete_file_with_space_and_regenerate_patch(void)
+{
+       const char *content = PATCH_DELETE_FILE_WITH_SPACE;
+       git_diff *diff = NULL;
+       git_buf buf = GIT_BUF_INIT;
+
+       cl_git_pass(git_diff_from_buffer(&diff, content, strlen(content)));
+       cl_git_pass(git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH));
+
+       git_buf_dispose(&buf);
+       git_diff_free(diff);
+}
+
 void test_diff_parse__crlf(void)
 {
        const char *text = PATCH_CRLF;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/main.c 
new/libgit2-1.4.3/tests/main.c
--- old/libgit2-1.4.2/tests/main.c      2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/tests/main.c      2022-04-12 22:17:07.000000000 +0200
@@ -26,6 +26,7 @@
 
        cl_global_trace_register();
        cl_sandbox_set_search_path_defaults();
+       cl_sandbox_disable_ownership_validation();
 
        /* Run the test suite */
        res = clar_test_run();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/online/clone.c 
new/libgit2-1.4.3/tests/online/clone.c
--- old/libgit2-1.4.2/tests/online/clone.c      2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/online/clone.c      2022-04-12 22:17:07.000000000 
+0200
@@ -8,9 +8,9 @@
 
 #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository";
 #define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository";
-#define BB_REPO_URL 
"https://libg...@bitbucket.org/libgit2/testgitrepository.git";
-#define BB_REPO_URL_WITH_PASS 
"https://libgit3:libg...@bitbucket.org/libgit2/testgitrepository.git";
-#define BB_REPO_URL_WITH_WRONG_PASS 
"https://libgit3:wr...@bitbucket.org/libgit2/testgitrepository.git";
+#define BB_REPO_URL 
"https://libgit2-t...@bitbucket.org/libgit2-test/testgitrepository.git";
+#define BB_REPO_URL_WITH_PASS 
"https://libgit2-test:yt77ppm2nq8w4tyjg...@bitbucket.org/libgit2-test/testgitrepository.git";
+#define BB_REPO_URL_WITH_WRONG_PASS 
"https://libgit2-test:wr...@bitbucket.org/libgit2-test/testgitrepository.git";
 #define GOOGLESOURCE_REPO_URL 
"https://chromium.googlesource.com/external/github.com/sergi/go-diff";
 
 #define SSH_REPO_URL "ssh://github.com/libgit2/TestGitRepository"
@@ -413,7 +413,7 @@
 
 void test_online_clone__credentials_via_custom_headers(void)
 {
-       const char *creds = "libgit3:libgit3";
+       const char *creds = "libgit2-test:YT77Ppm2nq8w4TYjGS8U";
        git_str auth = GIT_STR_INIT;
 
        cl_git_pass(git_str_puts(&auth, "Authorization: Basic "));
@@ -421,7 +421,7 @@
        g_options.fetch_opts.custom_headers.count = 1;
        g_options.fetch_opts.custom_headers.strings = &auth.ptr;
 
-       cl_git_pass(git_clone(&g_repo, 
"https://bitbucket.org/libgit2/testgitrepository.git";, "./foo", &g_options));
+       cl_git_pass(git_clone(&g_repo, 
"https://bitbucket.org/libgit2-test/testgitrepository.git";, "./foo", 
&g_options));
 
        git_str_dispose(&auth);
 }
@@ -429,7 +429,7 @@
 void test_online_clone__bitbucket_style(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit3", "libgit3"
+               "libgit2-test", "YT77Ppm2nq8w4TYjGS8U"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
@@ -443,7 +443,7 @@
 void test_online_clone__bitbucket_uses_creds_in_url(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit2", "wrong"
+               "libgit2-test", "wrong"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
@@ -461,7 +461,7 @@
 void test_online_clone__bitbucket_falls_back_to_specified_creds(void)
 {
        git_credential_userpass_payload user_pass = {
-               "libgit2", "libgit2"
+               "libgit2-test", "libgit2"
        };
 
        g_options.fetch_opts.callbacks.credentials = git_credential_userpass;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/online/fetch.c 
new/libgit2-1.4.3/tests/online/fetch.c
--- old/libgit2-1.4.2/tests/online/fetch.c      2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/online/fetch.c      2022-04-12 22:17:07.000000000 
+0200
@@ -321,3 +321,32 @@
        git_object_free(obj);
        git_remote_free(remote);
 }
+
+void test_online_fetch__reachable_commit_without_destination(void)
+{
+       git_remote *remote;
+       git_strarray refspecs;
+       git_object *obj;
+       git_oid expected_id;
+       git_str fetchhead = GIT_STR_INIT;
+       char *refspec = "2c349335b7f797072cf729c4f3bb0914ecb6dec9";
+
+       refspecs.strings = &refspec;
+       refspecs.count = 1;
+
+       git_oid_fromstr(&expected_id, 
"2c349335b7f797072cf729c4f3bb0914ecb6dec9");
+
+       cl_git_pass(git_remote_create(&remote, _repo, "test",
+               "https://github.com/libgit2/TestGitRepository";));
+       cl_git_pass(git_remote_fetch(remote, &refspecs, NULL, NULL));
+
+       cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&obj, _repo, 
"refs/success"));
+
+       cl_git_pass(git_futils_readbuffer(&fetchhead, 
"./fetch/.git/FETCH_HEAD"));
+       cl_assert_equal_s(fetchhead.ptr,
+               
"2c349335b7f797072cf729c4f3bb0914ecb6dec9\t\t'2c349335b7f797072cf729c4f3bb0914ecb6dec9'
 of https://github.com/libgit2/TestGitRepository\n";);
+
+       git_str_dispose(&fetchhead);
+       git_object_free(obj);
+       git_remote_free(remote);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/patch/patch_common.h 
new/libgit2-1.4.3/tests/patch/patch_common.h
--- old/libgit2-1.4.2/tests/patch/patch_common.h        2022-02-26 
20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/tests/patch/patch_common.h        2022-04-12 
22:17:07.000000000 +0200
@@ -933,6 +933,15 @@
        "@@ -0,0 +1 @@\n" \
        "+a\n"
 
+#define PATCH_DELETE_FILE_WITH_SPACE \
+       "diff --git a/sp ace.txt b/sp ace.txt\n" \
+       "deleted file mode 100644\n" \
+       "index 789819226..000000000\n" \
+       "--- a/sp ace.txt\n" \
+       "+++ /dev/null\n" \
+       "@@ -1 +0,0 @@\n" \
+       "-a\n"
+
 #define PATCH_CRLF \
        "diff --git a/test-file b/test-file\r\n" \
        "new file mode 100644\r\n" \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/repo/config.c 
new/libgit2-1.4.3/tests/repo/config.c
--- old/libgit2-1.4.2/tests/repo/config.c       2022-02-26 20:50:04.000000000 
+0100
+++ new/libgit2-1.4.3/tests/repo/config.c       2022-04-12 22:17:07.000000000 
+0200
@@ -28,7 +28,6 @@
        cl_assert(!git_fs_path_isdir("alternate"));
 
        cl_fixture_cleanup("empty_standard_repo");
-
 }
 
 void test_repo_config__can_open_global_when_there_is_no_file(void)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libgit2-1.4.2/tests/repo/open.c 
new/libgit2-1.4.3/tests/repo/open.c
--- old/libgit2-1.4.2/tests/repo/open.c 2022-02-26 20:50:04.000000000 +0100
+++ new/libgit2-1.4.3/tests/repo/open.c 2022-04-12 22:17:07.000000000 +0200
@@ -3,13 +3,30 @@
 #include "sysdir.h"
 #include <ctype.h>
 
+static int validate_ownership = 0;
+static git_buf config_path = GIT_BUF_INIT;
+
+void test_repo_open__initialize(void)
+{
+       cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, 
GIT_CONFIG_LEVEL_GLOBAL, &config_path));
+       cl_git_pass(git_libgit2_opts(GIT_OPT_GET_OWNER_VALIDATION, 
&validate_ownership));
+}
 
 void test_repo_open__cleanup(void)
 {
        cl_git_sandbox_cleanup();
+       cl_fixture_cleanup("empty_standard_repo");
+       cl_fixture_cleanup("__global_config");
 
        if (git_fs_path_isdir("alternate"))
                git_futils_rmdir_r("alternate", NULL, GIT_RMDIR_REMOVE_FILES);
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_NONE);
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, 
GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr));
+       git_buf_dispose(&config_path);
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 
validate_ownership));
 }
 
 void test_repo_open__bare_empty_repo(void)
@@ -453,3 +470,133 @@
        git_repository_free(barerepo);
 }
 
+void test_repo_open__validates_dir_ownership(void)
+{
+       git_repository *repo;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", 
"empty_standard_repo/.git"));
+
+       /* When the current user owns the repo config, that's acceptable */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_CURRENT_USER);
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       /* When the system user owns the repo config, fail */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_SYSTEM);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* When an unknown user owns the repo config, fail */
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+}
+
+void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
+{
+       git_repository *repo;
+       git_str config_path = GIT_STR_INIT,
+               config_filename = GIT_STR_INIT,
+               config_data = GIT_STR_INIT;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", 
"empty_standard_repo/.git"));
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* Add safe.directory options to the global configuration */
+       git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
+       cl_must_pass(p_mkdir(config_path.ptr, 0777));
+       git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, 
config_path.ptr);
+
+       git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = /non/existent/path\n" \
+               "\tdirectory = /\n" \
+               "\tdirectory = c:\\\\temp\n" \
+               "\tdirectory = %s/%s\n" \
+               "\tdirectory = /tmp\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       git_str_dispose(&config_path);
+       git_str_dispose(&config_filename);
+       git_str_dispose(&config_data);
+}
+
+void test_repo_open__can_reset_safe_directory_list(void)
+{
+       git_repository *repo;
+       git_str config_path = GIT_STR_INIT,
+               config_filename = GIT_STR_INIT,
+               config_data = GIT_STR_INIT;
+
+       cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+
+       cl_fixture_sandbox("empty_standard_repo");
+       cl_git_pass(cl_rename("empty_standard_repo/.gitted", 
"empty_standard_repo/.git"));
+
+       git_fs_path__set_owner(GIT_FS_PATH_MOCK_OWNER_OTHER);
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* Add safe.directory options to the global configuration */
+       git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
+       cl_must_pass(p_mkdir(config_path.ptr, 0777));
+       git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, 
config_path.ptr);
+
+       git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+
+       /* The blank resets our sandbox directory and opening fails */
+
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = %s/%s\n" \
+               "\tdirectory = \n" \
+               "\tdirectory = /tmp\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_fail(git_repository_open(&repo, "empty_standard_repo"));
+
+       /* The blank resets tmp and allows subsequent declarations to succeed */
+
+       git_str_clear(&config_data);
+       git_str_printf(&config_data,
+               "[foo]\n" \
+               "\tbar = Foobar\n" \
+               "\tbaz = Baz!\n" \
+               "[safe]\n" \
+               "\tdirectory = /tmp\n" \
+               "\tdirectory = \n" \
+               "\tdirectory = %s/%s\n" \
+               "[bar]\n" \
+               "\tfoo = barfoo\n",
+               clar_sandbox_path(), "empty_standard_repo");
+       cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+       cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+       git_repository_free(repo);
+
+       git_str_dispose(&config_path);
+       git_str_dispose(&config_filename);
+       git_str_dispose(&config_data);
+}

Reply via email to