]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Sync with 2.34.8
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Sat, 11 Mar 2023 19:58:19 +0000 (20:58 +0100)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Mon, 17 Apr 2023 19:15:59 +0000 (21:15 +0200)
* maint-2.34: (28 commits)
  Git 2.34.8
  Git 2.33.8
  Git 2.32.7
  Git 2.31.8
  tests: avoid using `test_i18ncmp`
  Git 2.30.9
  gettext: avoid using gettext if the locale dir is not present
  apply --reject: overwrite existing `.rej` symlink if it exists
  http.c: clear the 'finished' member once we are done with it
  clone.c: avoid "exceeds maximum object size" error with GCC v12.x
  range-diff: use ssize_t for parsed "len" in read_patches()
  range-diff: handle unterminated lines in read_patches()
  range-diff: drop useless "offset" variable from read_patches()
  t5604: GETTEXT_POISON fix, conclusion
  t5604: GETTEXT_POISON fix, part 1
  t5619: GETTEXT_POISON fix
  t0003: GETTEXT_POISON fix, conclusion
  t0003: GETTEXT_POISON fix, part 1
  t0033: GETTEXT_POISON fix
  http: support CURLOPT_PROTOCOLS_STR
  http: prefer CURLOPT_SEEKFUNCTION to CURLOPT_IOCTLFUNCTION
  ...

19 files changed:
.github/workflows/main.yml
Documentation/RelNotes/2.30.9.txt [new file with mode: 0644]
Documentation/RelNotes/2.31.8.txt [new file with mode: 0644]
Documentation/RelNotes/2.32.7.txt [new file with mode: 0644]
Documentation/RelNotes/2.33.8.txt [new file with mode: 0644]
Documentation/RelNotes/2.34.8.txt [new file with mode: 0644]
apply.c
ci/install-dependencies.sh
ci/lib.sh
compat/nedmalloc/nedmalloc.c
compat/win32/syslog.c
config.c
dir.c
gettext.c
gettext.h
http.c
t/t0033-safe-directory.sh
t/t1300-config.sh
t/t4115-apply-symlink.sh

index c35200defb9357b6438ba3391bb4e17fed67acdc..352772e60702b257d1672a93a46ff1934b41b316 100644 (file)
@@ -232,12 +232,12 @@ jobs:
           - jobname: linux-gcc
             cc: gcc
             cc_package: gcc-8
-            pool: ubuntu-latest
+            pool: ubuntu-20.04
           - jobname: linux-TEST-vars
             cc: gcc
             os: ubuntu
             cc_package: gcc-8
-            pool: ubuntu-latest
+            pool: ubuntu-20.04
           - jobname: osx-clang
             cc: clang
             pool: macos-latest
@@ -305,7 +305,7 @@ jobs:
     if: needs.ci-config.outputs.enabled == 'yes'
     env:
       jobname: StaticAnalysis
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-22.04
     steps:
     - uses: actions/checkout@v2
     - run: ci/install-dependencies.sh
diff --git a/Documentation/RelNotes/2.30.9.txt b/Documentation/RelNotes/2.30.9.txt
new file mode 100644 (file)
index 0000000..708d626
--- /dev/null
@@ -0,0 +1,43 @@
+Git v2.30.9 Release Notes
+=========================
+
+This release addresses the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007.
+
+
+Fixes since v2.30.8
+-------------------
+
+ * CVE-2023-25652:
+
+   By feeding specially crafted input to `git apply --reject`, a
+   path outside the working tree can be overwritten with partially
+   controlled contents (corresponding to the rejected hunk(s) from
+   the given patch).
+
+ * CVE-2023-25815:
+
+   When Git is compiled with runtime prefix support and runs without
+   translated messages, it still used the gettext machinery to
+   display messages, which subsequently potentially looked for
+   translated messages in unexpected places. This allowed for
+   malicious placement of crafted messages.
+
+ * CVE-2023-29007:
+
+   When renaming or deleting a section from a configuration file,
+   certain malicious configuration values may be misinterpreted as
+   the beginning of a new configuration section, leading to arbitrary
+   configuration injection.
+
+Credit for finding CVE-2023-25652 goes to Ry0taK, and the fix was
+developed by Taylor Blau, Junio C Hamano and Johannes Schindelin,
+with the help of Linus Torvalds.
+
+Credit for finding CVE-2023-25815 goes to Maxime Escourbiac and
+Yassine BENGANA of Michelin, and the fix was developed by Johannes
+Schindelin.
+
+Credit for finding CVE-2023-29007 goes to André Baptista and Vítor Pinho
+of Ethiack, and the fix was developed by Taylor Blau, and Johannes
+Schindelin, with help from Jeff King, and Patrick Steinhardt.
diff --git a/Documentation/RelNotes/2.31.8.txt b/Documentation/RelNotes/2.31.8.txt
new file mode 100644 (file)
index 0000000..0aa3080
--- /dev/null
@@ -0,0 +1,6 @@
+Git v2.31.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 to address the
+security issues CVE-2023-25652, CVE-2023-25815, and CVE-2023-29007;
+see the release notes for that version for details.
diff --git a/Documentation/RelNotes/2.32.7.txt b/Documentation/RelNotes/2.32.7.txt
new file mode 100644 (file)
index 0000000..7bb3538
--- /dev/null
@@ -0,0 +1,7 @@
+Git v2.32.7 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9 and v2.31.8 to
+address the security issues CVE-2023-25652, CVE-2023-25815, and
+CVE-2023-29007; see the release notes for these versions for
+details.
diff --git a/Documentation/RelNotes/2.33.8.txt b/Documentation/RelNotes/2.33.8.txt
new file mode 100644 (file)
index 0000000..d8cf4c7
--- /dev/null
@@ -0,0 +1,7 @@
+Git v2.33.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8 and
+v2.32.7 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/Documentation/RelNotes/2.34.8.txt b/Documentation/RelNotes/2.34.8.txt
new file mode 100644 (file)
index 0000000..2b5bd7d
--- /dev/null
@@ -0,0 +1,7 @@
+Git v2.34.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7 and v2.33.8 to address the security issues CVE-2023-25652,
+CVE-2023-25815, and CVE-2023-29007; see the release notes for these
+versions for details.
diff --git a/apply.c b/apply.c
index fc6f484a9fd4cfc8cc07e5557bf1a319fbae4fb4..47f26860a8bbbab979e8ade4d259958e628a5b7a 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -4584,7 +4584,7 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
        FILE *rej;
        char namebuf[PATH_MAX];
        struct fragment *frag;
-       int cnt = 0;
+       int fd, cnt = 0;
        struct strbuf sb = STRBUF_INIT;
 
        for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
@@ -4624,7 +4624,17 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
        memcpy(namebuf, patch->new_name, cnt);
        memcpy(namebuf + cnt, ".rej", 5);
 
-       rej = fopen(namebuf, "w");
+       fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+       if (fd < 0) {
+               if (errno != EEXIST)
+                       return error_errno(_("cannot open %s"), namebuf);
+               if (unlink(namebuf))
+                       return error_errno(_("cannot unlink '%s'"), namebuf);
+               fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
+               if (fd < 0)
+                       return error_errno(_("cannot open %s"), namebuf);
+       }
+       rej = fdopen(fd, "w");
        if (!rej)
                return error_errno(_("cannot open %s"), namebuf);
 
index dbcebad2fb293303f9271850094a29c3a249bda6..df6c61713cc6771ddabc9ab7d425e4dab161feda 100755 (executable)
@@ -5,17 +5,17 @@
 
 . ${0%/*}/lib.sh
 
-P4WHENCE=http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION
+P4WHENCE=https://cdist2.perforce.com/perforce/r21.2
 LFSWHENCE=https://github.com/github/git-lfs/releases/download/v$LINUX_GIT_LFS_VERSION
 UBUNTU_COMMON_PKGS="make libssl-dev libcurl4-openssl-dev libexpat-dev
  tcl tk gettext zlib1g-dev perl-modules liberror-perl libauthen-sasl-perl
  libemail-valid-perl libio-socket-ssl-perl libnet-smtp-ssl-perl"
 
 case "$runs_on_pool" in
-ubuntu-latest)
+ubuntu-*)
        sudo apt-get -q update
        sudo apt-get -q -y install language-pack-is libsvn-perl apache2 \
-               $UBUNTU_COMMON_PKGS $CC_PACKAGE
+               $UBUNTU_COMMON_PKGS $PYTHON_PACKAGE
        mkdir --parents "$P4_PATH"
        pushd "$P4_PATH"
                wget --quiet "$P4WHENCE/bin.linux26x86_64/p4d"
@@ -37,13 +37,15 @@ macos-latest)
        test -z "$BREW_INSTALL_PACKAGES" ||
        brew install $BREW_INSTALL_PACKAGES
        brew link --force gettext
-       brew install --cask --no-quarantine perforce || {
-               # Update the definitions and try again
-               cask_repo="$(brew --repository)"/Library/Taps/homebrew/homebrew-cask &&
-               git -C "$cask_repo" pull --no-stat --ff-only &&
-               brew install --cask --no-quarantine perforce
-       } ||
-       brew install homebrew/cask/perforce
+       mkdir -p $HOME/bin
+       (
+               cd $HOME/bin
+               wget -q "$P4WHENCE/bin.macosx1015x86_64/helix-core-server.tgz" &&
+               tar -xf helix-core-server.tgz &&
+               sudo xattr -d com.apple.quarantine p4 p4d 2>/dev/null || true
+       )
+       PATH="$PATH:${HOME}/bin"
+       export PATH
 
        if test -n "$CC_PACKAGE"
        then
@@ -81,9 +83,9 @@ esac
 if type p4d >/dev/null && type p4 >/dev/null
 then
        echo "$(tput setaf 6)Perforce Server Version$(tput sgr0)"
-       p4d -V | grep Rev.
+       p4d -V
        echo "$(tput setaf 6)Perforce Client Version$(tput sgr0)"
-       p4 -V | grep Rev.
+       p4 -V
 fi
 if type git-lfs >/dev/null
 then
index 9d28ab50fb4462a1b064e8c89cd5f13518fd86cd..5e01a927f105b450412c346590cf07eaa4f07578 100755 (executable)
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -157,18 +157,18 @@ export GIT_TEST_CLONE_2GB=true
 export SKIP_DASHED_BUILT_INS=YesPlease
 
 case "$runs_on_pool" in
-ubuntu-latest)
+ubuntu-*)
        if test "$jobname" = "linux-gcc-default"
        then
                break
        fi
 
+       PYTHON_PACKAGE=python2
        if [ "$jobname" = linux-gcc ]
        then
-               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python3"
-       else
-               MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/python2"
+               PYTHON_PACKAGE=python3
        fi
+       MAKEFLAGS="$MAKEFLAGS PYTHON_PATH=/usr/bin/$PYTHON_PACKAGE"
 
        export GIT_TEST_HTTPD=true
 
@@ -177,7 +177,6 @@ ubuntu-latest)
        # were recorded in the Homebrew database upon creating the OS X
        # image.
        # Keep that in mind when you encounter a broken OS X build!
-       export LINUX_P4_VERSION="16.2"
        export LINUX_GIT_LFS_VERSION="1.5.2"
 
        P4_PATH="$HOME/custom/p4"
index edb438a7776aed1c1559352ce3b32e051cac806a..2c0ace7075a34e43b929e91a5c1ffcffe4d135b5 100644 (file)
@@ -323,7 +323,6 @@ static NOINLINE void RemoveCacheEntries(nedpool *p, threadcache *tc, unsigned in
 }
 static void DestroyCaches(nedpool *p) THROWSPEC
 {
-       if(p->caches)
        {
                threadcache *tc;
                int n;
index 161978d720aed9db5a00c77d1c6bd9a073544f15..1f8d8934cc90dc2a5988265c555271c8afd18084 100644 (file)
@@ -43,6 +43,7 @@ void syslog(int priority, const char *fmt, ...)
        va_end(ap);
 
        while ((pos = strstr(str, "%1")) != NULL) {
+               size_t offset = pos - str;
                char *oldstr = str;
                str = realloc(str, st_add(++str_len, 1));
                if (!str) {
@@ -50,6 +51,7 @@ void syslog(int priority, const char *fmt, ...)
                        warning_errno("realloc failed");
                        return;
                }
+               pos = str + offset;
                memmove(pos + 2, pos + 1, strlen(pos));
                pos[1] = ' ';
        }
index 2bffa8d4a01ba1f281d6e6fd95f35bf133cbd9c5..6a01938222f65e574ee7dfac8d4005fc1c350c20 100644 (file)
--- a/config.c
+++ b/config.c
@@ -3192,9 +3192,10 @@ void git_config_set_multivar(const char *key, const char *value,
                                        flags);
 }
 
-static int section_name_match (const char *buf, const char *name)
+static size_t section_name_match (const char *buf, const char *name)
 {
-       int i = 0, j = 0, dot = 0;
+       size_t i = 0, j = 0;
+       int dot = 0;
        if (buf[i] != '[')
                return 0;
        for (i = 1; buf[i] && buf[i] != ']'; i++) {
@@ -3247,6 +3248,8 @@ static int section_name_is_ok(const char *name)
        return 1;
 }
 
+#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
+
 /* if new_name == NULL, the section is removed instead */
 static int git_config_copy_or_rename_section_in_file(const char *config_filename,
                                      const char *old_name,
@@ -3256,11 +3259,12 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
        char *filename_buf = NULL;
        struct lock_file lock = LOCK_INIT;
        int out_fd;
-       char buf[1024];
+       struct strbuf buf = STRBUF_INIT;
        FILE *config_file = NULL;
        struct stat st;
        struct strbuf copystr = STRBUF_INIT;
        struct config_store_data store;
+       uint32_t line_nr = 0;
 
        memset(&store, 0, sizeof(store));
 
@@ -3297,16 +3301,25 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
                goto out;
        }
 
-       while (fgets(buf, sizeof(buf), config_file)) {
-               unsigned i;
-               int length;
+       while (!strbuf_getwholeline(&buf, config_file, '\n')) {
+               size_t i, length;
                int is_section = 0;
-               char *output = buf;
-               for (i = 0; buf[i] && isspace(buf[i]); i++)
+               char *output = buf.buf;
+
+               line_nr++;
+
+               if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
+                       ret = error(_("refusing to work with overly long line "
+                                     "in '%s' on line %"PRIuMAX),
+                                   config_filename, (uintmax_t)line_nr);
+                       goto out;
+               }
+
+               for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
                        ; /* do nothing */
-               if (buf[i] == '[') {
+               if (buf.buf[i] == '[') {
                        /* it's a section */
-                       int offset;
+                       size_t offset;
                        is_section = 1;
 
                        /*
@@ -3323,7 +3336,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
                                strbuf_reset(&copystr);
                        }
 
-                       offset = section_name_match(&buf[i], old_name);
+                       offset = section_name_match(&buf.buf[i], old_name);
                        if (offset > 0) {
                                ret++;
                                if (new_name == NULL) {
@@ -3398,6 +3411,7 @@ out:
 out_no_rollback:
        free(filename_buf);
        config_store_data_clear(&store);
+       strbuf_release(&buf);
        return ret;
 }
 
diff --git a/dir.c b/dir.c
index d91295f2bcdcf86f0b1c41a32ac6a17d5d3cf65e..689c98cb4a0ea6bb56bab6f7d20dfde365d35edb 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -3074,6 +3074,15 @@ char *git_url_basename(const char *repo, int is_bundle, int is_bare)
                        end--;
        }
 
+       /*
+        * It should not be possible to overflow `ptrdiff_t` by passing in an
+        * insanely long URL, but GCC does not know that and will complain
+        * without this check.
+        */
+       if (end - start < 0)
+               die(_("No directory name could be guessed.\n"
+                     "Please specify a directory on the command line"));
+
        /*
         * Strip trailing port number if we've got only a
         * hostname (that is, there is no dir separator but a
index bb5ba1fe7cc5979255fe79fd8dfc0085fc8df8f1..7fff88c8da7e216700eb14cfd81a340f904eceb9 100644 (file)
--- a/gettext.c
+++ b/gettext.c
@@ -102,6 +102,8 @@ static void init_gettext_charset(const char *domain)
                setlocale(LC_CTYPE, "C");
 }
 
+int git_gettext_enabled = 0;
+
 void git_setup_gettext(void)
 {
        const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
@@ -121,6 +123,8 @@ void git_setup_gettext(void)
        init_gettext_charset("git");
        textdomain("git");
 
+       git_gettext_enabled = 1;
+
        free(p);
 }
 
index d209911ebb80c164fb93073d054fd1ff7acb8da3..484cafa5628850930f8536c6c4e79fb26847153d 100644 (file)
--- a/gettext.h
+++ b/gettext.h
 #define FORMAT_PRESERVING(n) __attribute__((format_arg(n)))
 
 #ifndef NO_GETTEXT
+extern int git_gettext_enabled;
 void git_setup_gettext(void);
 int gettext_width(const char *s);
 #else
+#define git_gettext_enabled (0)
 static inline void git_setup_gettext(void)
 {
 }
@@ -45,12 +47,16 @@ static inline FORMAT_PRESERVING(1) const char *_(const char *msgid)
 {
        if (!*msgid)
                return "";
+       if (!git_gettext_enabled)
+               return msgid;
        return gettext(msgid);
 }
 
 static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
 const char *Q_(const char *msgid, const char *plu, unsigned long n)
 {
+       if (!git_gettext_enabled)
+               return n == 1 ? msgid : plu;
        return ngettext(msgid, plu, n);
 }
 
diff --git a/http.c b/http.c
index 2a97d1773557710a1ebb8ac02ed72c2fc52d318d..bb8d8907120ebe8fb283f821f5dc8fa8713c6d96 100644 (file)
--- a/http.c
+++ b/http.c
@@ -1398,6 +1398,32 @@ void run_active_slot(struct active_request_slot *slot)
                        select(max_fd+1, &readfds, &writefds, &excfds, &select_timeout);
                }
        }
+
+       /*
+        * The value of slot->finished we set before the loop was used
+        * to set our "finished" variable when our request completed.
+        *
+        * 1. The slot may not have been reused for another requst
+        *    yet, in which case it still has &finished.
+        *
+        * 2. The slot may already be in-use to serve another request,
+        *    which can further be divided into two cases:
+        *
+        * (a) If call run_active_slot() hasn't been called for that
+        *     other request, slot->finished would have been cleared
+        *     by get_active_slot() and has NULL.
+        *
+        * (b) If the request did call run_active_slot(), then the
+        *     call would have updated slot->finished at the beginning
+        *     of this function, and with the clearing of the member
+        *     below, we would find that slot->finished is now NULL.
+        *
+        * In all cases, slot->finished has no useful information to
+        * anybody at this point.  Some compilers warn us for
+        * attempting to smuggle a pointer that is about to become
+        * invalid, i.e. &finished.  We clear it here to assure them.
+        */
+       slot->finished = NULL;
 }
 
 static void release_active_slot(struct active_request_slot *slot)
index 239d93f4d21141f5991f9fb409a4675ece0f98bd..22ae88398c722cc59241315ac5516c3f345b7174 100755 (executable)
@@ -9,7 +9,7 @@ export GIT_TEST_ASSUME_DIFFERENT_OWNER
 
 expect_rejected_dir () {
        test_must_fail git status 2>err &&
-       grep "safe.directory" err
+       grep "dubious ownership" err
 }
 
 test_expect_success 'safe.directory is not set' '
index 78359f1f4a2d736f44b84075013e647a7fab3660..9df05ac2300e4cf4fec039db4dc535d4a3add401 100755 (executable)
@@ -617,6 +617,36 @@ test_expect_success 'renaming to bogus section is rejected' '
        test_must_fail git config --rename-section branch.zwei "bogus name"
 '
 
+test_expect_success 'renaming a section with a long line' '
+       {
+               printf "[b]\\n" &&
+               printf "  c = d %1024s [a] e = f\\n" " " &&
+               printf "[a] g = h\\n"
+       } >y &&
+       git config -f y --rename-section a xyz &&
+       test_must_fail git config -f y b.e
+'
+
+test_expect_success 'renaming an embedded section with a long line' '
+       {
+               printf "[b]\\n" &&
+               printf "  c = d %1024s [a] [foo] e = f\\n" " " &&
+               printf "[a] g = h\\n"
+       } >y &&
+       git config -f y --rename-section a xyz &&
+       test_must_fail git config -f y foo.e
+'
+
+test_expect_success 'renaming a section with an overly-long line' '
+       {
+               printf "[b]\\n" &&
+               printf "  c = d %525000s e" " " &&
+               printf "[a] g = h\\n"
+       } >y &&
+       test_must_fail git config -f y --rename-section a xyz 2>err &&
+       grep "refusing to work with overly long line in .y. on line 2" err
+'
+
 cat >> .git/config << EOF
   [branch "zwei"] a = 1 [branch "vier"]
 EOF
index 65ac7df2d745c4f7a698baf23cc71c2a80221c3e..e95e6d4e7d6419236c1e8bb9bc519b05ea8efec3 100755 (executable)
@@ -126,4 +126,19 @@ test_expect_success SYMLINKS 'symlink escape when deleting file' '
        test_path_is_file .git/delete-me
 '
 
+test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' '
+       test_when_finished "git reset --hard && git clean -dfx" &&
+
+       test_commit file &&
+       echo modified >file.t &&
+       git diff -- file.t >patch &&
+       echo modified-again >file.t &&
+
+       ln -s foo file.t.rej &&
+       test_must_fail git apply patch --reject 2>err &&
+       test_i18ngrep "Rejected hunk" err &&
+       test_path_is_missing foo &&
+       test_path_is_file file.t.rej
+'
+
 test_done