config.c: disallow overly-long lines in `copy_or_rename_section_in_file()`

As a defense-in-depth measure to guard against any potentially-unknown buffer overflows in `copy_or_rename_section_in_file()`, refuse to work with overly-long lines in a gitconfig. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

Taylor Blau committed Apr 12, 2023 at 19:18 UTC 3bb3d6bac5f2b496dfa2862dc1a84cbfa9b4449a
2 files changed +23
config.c
+13
@@ -3083,6 +3083,8 @@ static int section_name_is_ok(const char *name)
3083 return 1;
3084 }
3085
3086 +#define GIT_CONFIG_MAX_LINE_LEN (512 * 1024)
3087 +
3088 /* if new_name == NULL, the section is removed instead */
3089 static int git_config_copy_or_rename_section_in_file(const char *config_filename,
3090 const char *old_name,
@@ -3097,6 +3099,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
3099 struct stat st;
3100 struct strbuf copystr = STRBUF_INIT;
3101 struct config_store_data store;
3102 + uint32_t line_nr = 0;
3103
3104 memset(&store, 0, sizeof(store));
3105
@@ -3137,6 +3140,16 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
3140 size_t i, length;
3141 int is_section = 0;
3142 char *output = buf.buf;
3143 +
3144 + line_nr++;
3145 +
3146 + if (buf.len >= GIT_CONFIG_MAX_LINE_LEN) {
3147 + ret = error(_("refusing to work with overly long line "
3148 + "in '%s' on line %"PRIuMAX),
3149 + config_filename, (uintmax_t)line_nr);
3150 + goto out;
3151 + }
3152 +
3153 for (i = 0; buf.buf[i] && isspace(buf.buf[i]); i++)
3154 ; /* do nothing */
3155 if (buf.buf[i] == '[') {
t/t1300-config.sh
+10
@@ -633,6 +633,16 @@ test_expect_success 'renaming an embedded section with a long line' '
633 test_must_fail git config -f y foo.e
634 '
635
636 +test_expect_success 'renaming a section with an overly-long line' '
637 + {
638 + printf "[b]\\n" &&
639 + printf " c = d %525000s e" " " &&
640 + printf "[a] g = h\\n"
641 + } >y &&
642 + test_must_fail git config -f y --rename-section a xyz 2>err &&
643 + test_i18ngrep "refusing to work with overly long line in .y. on line 2" err
644 +'
645 +
646 cat >> .git/config << EOF
647 [branch "zwei"] a = 1 [branch "vier"]
648 EOF