diff -up ./config.c.original ./config.c
--- ./config.c.original 2023-05-18 15:11:28.221121569 +0900
+++ ./config.c 2023-05-18 15:24:30.178828343 +0900
@@ -1701,6 +1701,8 @@ static int section_name_is_ok(const char
return 1;
}
+#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
+
/* if new_name == NULL, the section is removed instead */
int git_config_rename_section_in_file(const char *config_filename,
const char *old_name, const char *new_name)
@@ -1709,8 +1711,9 @@ int git_config_rename_section_in_file(co
char *filename_buf = NULL;
struct lock_file *lock;
int out_fd;
- char buf[1024];
+ struct strbuf buf = STRBUF_INIT;
FILE *config_file;
+ uint32_t line_nr = 0;
if (new_name && !section_name_is_ok(new_name)) {
ret = error("invalid section name: %s", new_name);
@@ -1732,15 +1735,25 @@ int git_config_rename_section_in_file(co
goto unlock_and_out;
}
- while (fgets(buf, sizeof(buf), config_file)) {
+ while (!strbuf_getwholeline(&buf, config_file, '\n')) {
int i;
int length;
- 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 = section_name_match(&buf[i], old_name);
+ int offset = section_name_match(&buf.buf[i], old_name);
if (offset > 0) {
ret++;
if (new_name == NULL) {
@@ -1785,6 +1798,7 @@ unlock_and_out:
ret = error("could not commit config file %s", config_filename);
out:
free(filename_buf);
+ strbuf_release(&buf);
return ret;
}
diff -up ./t/t1300-repo-config.sh.original ./t/t1300-repo-config.sh
--- ./t/t1300-repo-config.sh.original 2023-05-18 15:17:53.636877440 +0900
+++ ./t/t1300-repo-config.sh 2023-05-18 15:25:16.931647850 +0900
@@ -1122,4 +1122,34 @@ test_expect_failure 'adding a key into a
test_cmp expect .git/config
'
+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
+'
+
test_done