]> git.ipfire.org Git - thirdparty/git.git/commitdiff
config.c: disallow overly-long lines in `copy_or_rename_section_in_file()`
authorTaylor Blau <me@ttaylorr.com>
Wed, 12 Apr 2023 23:18:28 +0000 (19:18 -0400)
committerJohannes Schindelin <johannes.schindelin@gmx.de>
Mon, 17 Apr 2023 19:15:40 +0000 (21:15 +0200)
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>
config.c
t/t1300-config.sh

index e4189aa2d79f628bfe2a2ab673be5e0c20463505..b8194dfd8a78afaa07e8287bbdf31f1324883cfb 100644 (file)
--- a/config.c
+++ b/config.c
@@ -3083,6 +3083,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,
@@ -3097,6 +3099,7 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
        struct stat st;
        struct strbuf copystr = STRBUF_INIT;
        struct config_store_data store;
+       uint32_t line_nr = 0;
 
        memset(&store, 0, sizeof(store));
 
@@ -3137,6 +3140,16 @@ static int git_config_copy_or_rename_section_in_file(const char *config_filename
                size_t i, length;
                int is_section = 0;
                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.buf[i] == '[') {
index 24c13b91dbd669773041032f8156126c8b337da2..de564cb8e587a6cb6c17096051398a3963a5d041 100755 (executable)
@@ -633,6 +633,16 @@ test_expect_success 'renaming an embedded section with a long line' '
        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