Sync with 2.35.8

* maint-2.35: (29 commits)
  Git 2.35.8
  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
  ...
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index c35200d..352772e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -232,12 +232,12 @@
           - 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 @@
     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
index 0000000..708d626
--- /dev/null
+++ b/Documentation/RelNotes/2.30.9.txt
@@ -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
index 0000000..0aa3080
--- /dev/null
+++ b/Documentation/RelNotes/2.31.8.txt
@@ -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
index 0000000..7bb3538
--- /dev/null
+++ b/Documentation/RelNotes/2.32.7.txt
@@ -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
index 0000000..d8cf4c7
--- /dev/null
+++ b/Documentation/RelNotes/2.33.8.txt
@@ -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
index 0000000..2b5bd7d
--- /dev/null
+++ b/Documentation/RelNotes/2.34.8.txt
@@ -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/Documentation/RelNotes/2.35.8.txt b/Documentation/RelNotes/2.35.8.txt
new file mode 100644
index 0000000..3c9c094
--- /dev/null
+++ b/Documentation/RelNotes/2.35.8.txt
@@ -0,0 +1,7 @@
+Git v2.35.8 Release Notes
+=========================
+
+This release merges the fixes that appear in v2.30.9, v2.31.8,
+v2.32.7, v2.33.8 and v2.34.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/Makefile b/Makefile
index 61aadf3..9e9d610 100644
--- a/Makefile
+++ b/Makefile
@@ -1311,6 +1311,7 @@
 endif
 ifneq ($(filter leak,$(SANITIZERS)),)
 BASIC_CFLAGS += -DSUPPRESS_ANNOTATED_LEAKS
+BASIC_CFLAGS += -O0
 SANITIZE_LEAK = YesCompiledWithIt
 endif
 ifneq ($(filter address,$(SANITIZERS)),)
diff --git a/apply.c b/apply.c
index a957be0..5258314 100644
--- a/apply.c
+++ b/apply.c
@@ -4566,7 +4566,7 @@
 	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) {
@@ -4606,7 +4606,17 @@
 	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);
 
diff --git a/ci/install-dependencies.sh b/ci/install-dependencies.sh
index 107757a..a1a7b34 100755
--- a/ci/install-dependencies.sh
+++ b/ci/install-dependencies.sh
@@ -5,17 +5,17 @@
 
 . ${0%/*}/lib.sh
 
-P4WHENCE=https://cdist2.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 $CC_PACKAGE $PYTHON_PACKAGE
 	mkdir --parents "$P4_PATH"
 	pushd "$P4_PATH"
 		wget --quiet "$P4WHENCE/bin.linux26x86_64/p4d"
@@ -40,7 +40,7 @@
 	mkdir -p $HOME/bin
 	(
 		cd $HOME/bin
-		wget -q "https://cdist2.perforce.com/perforce/r21.2/bin.macosx1015x86_64/helix-core-server.tgz" &&
+		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
 	)
@@ -83,11 +83,9 @@
 if type p4d >/dev/null 2>&1 && type p4 >/dev/null 2>&1
 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.
-else
-	echo >&2 "WARNING: perforce wasn't installed, see above for clues why"
+	p4 -V
 fi
 if type git-lfs >/dev/null 2>&1
 then
diff --git a/ci/lib.sh b/ci/lib.sh
index 86e37da..916057a 100755
--- a/ci/lib.sh
+++ b/ci/lib.sh
@@ -157,18 +157,18 @@
 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 @@
 	# 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"
diff --git a/config.c b/config.c
index a5e11aa..ab98072 100644
--- a/config.c
+++ b/config.c
@@ -3433,9 +3433,10 @@
 					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++) {
@@ -3488,6 +3489,8 @@
 	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,
@@ -3497,11 +3500,12 @@
 	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));
 
@@ -3538,16 +3542,25 @@
 		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;
 
 			/*
@@ -3564,7 +3577,7 @@
 				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) {
@@ -3639,6 +3652,7 @@
 out_no_rollback:
 	free(filename_buf);
 	config_store_data_clear(&store);
+	strbuf_release(&buf);
 	return ret;
 }
 
diff --git a/gettext.c b/gettext.c
index bb5ba1f..7fff88c 100644
--- a/gettext.c
+++ b/gettext.c
@@ -102,6 +102,8 @@
 		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 @@
 	init_gettext_charset("git");
 	textdomain("git");
 
+	git_gettext_enabled = 1;
+
 	free(p);
 }
 
diff --git a/gettext.h b/gettext.h
index d209911..484cafa 100644
--- a/gettext.h
+++ b/gettext.h
@@ -29,9 +29,11 @@
 #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 @@
 {
 	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/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh
index 239d93f..22ae883 100755
--- a/t/t0033-safe-directory.sh
+++ b/t/t0033-safe-directory.sh
@@ -9,7 +9,7 @@
 
 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' '
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 7dd9b32..0c8c163 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -617,6 +617,36 @@
 	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
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 65ac7df..e95e6d4 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -126,4 +126,19 @@
 	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