diff -ur b/apply.c a/apply.c
--- b/apply.c 2020-06-01 17:49:27.000000000 +0200
+++ a/apply.c 2023-05-03 13:53:00.200547081 +0200
@@ -4516,7 +4516,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) {
@@ -4556,7 +4556,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 -ur b/builtin/clone.c a/builtin/clone.c
--- b/builtin/clone.c 2020-06-01 17:49:27.000000000 +0200
+++ a/builtin/clone.c 2023-05-03 13:52:23.803339233 +0200
@@ -248,6 +248,15 @@
while (start < end && is_dir_sep(end[-1]))
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
diff -ur b/compat/nedmalloc/nedmalloc.c a/compat/nedmalloc/nedmalloc.c
--- b/compat/nedmalloc/nedmalloc.c 2020-06-01 17:49:27.000000000 +0200
+++ a/compat/nedmalloc/nedmalloc.c 2023-05-03 13:51:33.546052246 +0200
@@ -323,7 +323,6 @@
}
static void DestroyCaches(nedpool *p) THROWSPEC
{
- if(p->caches)
{
threadcache *tc;
int n;
diff -ur b/compat/win32/syslog.c a/compat/win32/syslog.c
--- b/compat/win32/syslog.c 2020-06-01 17:49:27.000000000 +0200
+++ a/compat/win32/syslog.c 2023-05-03 13:51:35.154061429 +0200
@@ -43,6 +43,7 @@
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 @@
warning_errno("realloc failed");
return;
}
+ pos = str + offset;
memmove(pos + 2, pos + 1, strlen(pos));
pos[1] = ' ';
}
diff -ur b/config.c a/config.c
--- b/config.c 2020-06-01 17:49:27.000000000 +0200
+++ a/config.c 2023-05-03 13:50:49.378800030 +0200
@@ -3009,9 +3009,10 @@
multi_replace);
}
-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++) {
@@ -3064,6 +3065,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,
@@ -3073,11 +3076,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));
@@ -3114,16 +3118,25 @@
goto out;
}
- while (fgets(buf, sizeof(buf), config_file)) {
- int 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;
/*
@@ -3140,7 +3153,7 @@
strbuf_reset(©str);
}
- 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) {
@@ -3215,6 +3228,7 @@
out_no_rollback:
free(filename_buf);
config_store_data_clear(&store);
+ strbuf_release(&buf);
return ret;
}
diff -ur b/gettext.c a/gettext.c
--- b/gettext.c 2020-06-01 17:49:27.000000000 +0200
+++ a/gettext.c 2023-05-03 13:47:46.953758294 +0200
@@ -173,6 +173,8 @@
setlocale(LC_CTYPE, "C");
}
+int git_gettext_enabled = 0;
+
void git_setup_gettext(void)
{
const char *podir = getenv(GIT_TEXT_DOMAIN_DIR_ENVIRONMENT);
@@ -194,6 +196,8 @@
init_gettext_charset("git");
textdomain("git");
+ git_gettext_enabled = 1;
+
free(p);
}
diff -ur b/gettext.h a/gettext.h
--- b/gettext.h 2020-06-01 17:49:27.000000000 +0200
+++ a/gettext.h 2023-05-03 13:46:54.234457247 +0200
@@ -31,9 +31,11 @@
int use_gettext_poison(void);
#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)
{
use_gettext_poison(); /* getenv() reentrancy paranoia */
@@ -48,7 +50,8 @@
{
if (!*msgid)
return "";
- return use_gettext_poison() ? "# GETTEXT POISON #" : gettext(msgid);
+ return use_gettext_poison() ? "# GETTEXT POISON #" :
+ !git_gettext_enabled ? msgid : gettext(msgid);
}
static inline FORMAT_PRESERVING(1) FORMAT_PRESERVING(2)
@@ -56,6 +59,8 @@
{
if (use_gettext_poison())
return "# GETTEXT POISON #";
+ if (!git_gettext_enabled)
+ return n == 1 ? msgid : plu;
return ngettext(msgid, plu, n);
}
diff -ur b/range-diff.c a/range-diff.c
--- b/range-diff.c 2020-06-01 17:49:27.000000000 +0200
+++ a/range-diff.c 2023-05-03 13:44:54.980776256 +0200
@@ -25,17 +25,6 @@
struct object_id oid;
};
-static size_t find_end_of_line(char *buffer, unsigned long size)
-{
- char *eol = memchr(buffer, '\n', size);
-
- if (!eol)
- return size;
-
- *eol = '\0';
- return eol + 1 - buffer;
-}
-
/*
* Reads the patches into a string list, with the `util` field being populated
* as struct object_id (will need to be free()d).
@@ -48,7 +37,7 @@
struct patch_util *util = NULL;
int in_header = 1;
char *line, *current_filename = NULL;
- int offset, len;
+ ssize_t len;
size_t size;
argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
@@ -83,11 +72,18 @@
line = contents.buf;
size = contents.len;
- for (offset = 0; size > 0; offset += len, size -= len, line += len) {
+ for (; size > 0; size -= len, line += len) {
const char *p;
+ char *eol;
+
+ eol = memchr(line, '\n', size);
+ if (eol) {
+ *eol = '\0';
+ len = eol + 1 - line;
+ } else {
+ len = size;
+ }
- len = find_end_of_line(line, size);
- line[len - 1] = '\0';
if (skip_prefix(line, "commit ", &p)) {
if (util) {
string_list_append(list, buf.buf)->util = util;
@@ -129,7 +125,8 @@
strbuf_addch(&buf, '\n');
if (!util->diff_offset)
util->diff_offset = buf.len;
- line[len - 1] = '\n';
+ if (eol)
+ *eol = '\n';
orig_len = len;
len = parse_git_diff_header(&root, &linenr, 0, line,
len, size, &patch);
diff -ur b/t/t1300-config.sh a/t/t1300-config.sh
--- b/t/t1300-config.sh 2020-06-01 17:49:27.000000000 +0200
+++ a/t/t1300-config.sh 2023-05-03 13:39:43.864071831 +0200
@@ -616,6 +616,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 &&
+ test_i18ngrep "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 -ur b/t/t4115-apply-symlink.sh a/t/t4115-apply-symlink.sh
--- b/t/t4115-apply-symlink.sh 2020-06-01 17:49:27.000000000 +0200
+++ a/t/t4115-apply-symlink.sh 2023-05-03 13:39:01.453839938 +0200
@@ -44,4 +44,17 @@
'
+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
Only in a: .vscode