]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fsck: refactor `fsck_blob()` to allow for more checks
authorPatrick Steinhardt <ps@pks.im>
Thu, 1 Dec 2022 14:45:57 +0000 (15:45 +0100)
committerJunio C Hamano <gitster@pobox.com>
Fri, 9 Dec 2022 08:05:00 +0000 (17:05 +0900)
In general, we don't need to validate blob contents as they are opaque
blobs about whose content Git doesn't need to care about. There are some
exceptions though when blobs are linked into trees so that they would be
interpreted by Git. We only have a single such check right now though,
which is the one for gitmodules that has been added in the context of
CVE-2018-11235.

Now we have found another vulnerability with gitattributes that can lead
to out-of-bounds writes and reads. So let's refactor `fsck_blob()` so
that it is more extensible and can check different types of blobs.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
fsck.c

diff --git a/fsck.c b/fsck.c
index 3ec500d707aaf602e4e1c12139ccad075feb8046..ddcb2d264cd9574834523c957c9654a8981c7325 100644 (file)
--- a/fsck.c
+++ b/fsck.c
@@ -1170,38 +1170,41 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
 static int fsck_blob(const struct object_id *oid, const char *buf,
                     unsigned long size, struct fsck_options *options)
 {
-       struct fsck_gitmodules_data data;
-       struct config_options config_opts = { 0 };
-
-       if (!oidset_contains(&options->gitmodules_found, oid))
-               return 0;
-       oidset_insert(&options->gitmodules_done, oid);
+       int ret = 0;
 
        if (object_on_skiplist(options, oid))
                return 0;
 
-       if (!buf) {
-               /*
-                * A missing buffer here is a sign that the caller found the
-                * blob too gigantic to load into memory. Let's just consider
-                * that an error.
-                */
-               return report(options, oid, OBJ_BLOB,
-                             FSCK_MSG_GITMODULES_LARGE,
-                             ".gitmodules too large to parse");
+       if (oidset_contains(&options->gitmodules_found, oid)) {
+               struct config_options config_opts = { 0 };
+               struct fsck_gitmodules_data data;
+
+               oidset_insert(&options->gitmodules_done, oid);
+
+               if (!buf) {
+                       /*
+                        * A missing buffer here is a sign that the caller found the
+                        * blob too gigantic to load into memory. Let's just consider
+                        * that an error.
+                        */
+                       return report(options, oid, OBJ_BLOB,
+                                       FSCK_MSG_GITMODULES_LARGE,
+                                       ".gitmodules too large to parse");
+               }
+
+               data.oid = oid;
+               data.options = options;
+               data.ret = 0;
+               config_opts.error_action = CONFIG_ERROR_SILENT;
+               if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
+                                       ".gitmodules", buf, size, &data, &config_opts))
+                       data.ret |= report(options, oid, OBJ_BLOB,
+                                       FSCK_MSG_GITMODULES_PARSE,
+                                       "could not parse gitmodules blob");
+               ret |= data.ret;
        }
 
-       data.oid = oid;
-       data.options = options;
-       data.ret = 0;
-       config_opts.error_action = CONFIG_ERROR_SILENT;
-       if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
-                               ".gitmodules", buf, size, &data, &config_opts))
-               data.ret |= report(options, oid, OBJ_BLOB,
-                                  FSCK_MSG_GITMODULES_PARSE,
-                                  "could not parse gitmodules blob");
-
-       return data.ret;
+       return ret;
 }
 
 int fsck_object(struct object *obj, void *data, unsigned long size,