fsck: refactor `fsck_blob()` to allow for more checks
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>
Patrick Steinhardt committed
Dec 1, 2022 at 15:45 UTC
bb3a9265e505e9593faa260860f9b8929af0963e
1 file changed
+29
-26
fsck.c
+29
-26
@@ -1170,38 +1170,41 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
1170
static int fsck_blob(const struct object_id *oid, const char *buf,
1171
unsigned long size, struct fsck_options *options)
1172
{
1173
- struct fsck_gitmodules_data data;
1174
- struct config_options config_opts = { 0 };
1175
-
1176
- if (!oidset_contains(&options->gitmodules_found, oid))
1177
- return 0;
1178
- oidset_insert(&options->gitmodules_done, oid);
1173
+ int ret = 0;
1174
1175
if (object_on_skiplist(options, oid))
1176
return 0;
1177
1183
- if (!buf) {
1184
- /*
1185
- * A missing buffer here is a sign that the caller found the
1186
- * blob too gigantic to load into memory. Let's just consider
1187
- * that an error.
1188
- */
1189
- return report(options, oid, OBJ_BLOB,
1190
- FSCK_MSG_GITMODULES_LARGE,
1191
- ".gitmodules too large to parse");
1178
+ if (oidset_contains(&options->gitmodules_found, oid)) {
1179
+ struct config_options config_opts = { 0 };
1180
+ struct fsck_gitmodules_data data;
1181
+
1182
+ oidset_insert(&options->gitmodules_done, oid);
1183
+
1184
+ if (!buf) {
1185
+ /*
1186
+ * A missing buffer here is a sign that the caller found the
1187
+ * blob too gigantic to load into memory. Let's just consider
1188
+ * that an error.
1189
+ */
1190
+ return report(options, oid, OBJ_BLOB,
1191
+ FSCK_MSG_GITMODULES_LARGE,
1192
+ ".gitmodules too large to parse");
1193
+ }
1194
+
1195
+ data.oid = oid;
1196
+ data.options = options;
1197
+ data.ret = 0;
1198
+ config_opts.error_action = CONFIG_ERROR_SILENT;
1199
+ if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
1200
+ ".gitmodules", buf, size, &data, &config_opts))
1201
+ data.ret |= report(options, oid, OBJ_BLOB,
1202
+ FSCK_MSG_GITMODULES_PARSE,
1203
+ "could not parse gitmodules blob");
1204
+ ret |= data.ret;
1205
}
1206
1194
- data.oid = oid;
1195
- data.options = options;
1196
- data.ret = 0;
1197
- config_opts.error_action = CONFIG_ERROR_SILENT;
1198
- if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB,
1199
- ".gitmodules", buf, size, &data, &config_opts))
1200
- data.ret |= report(options, oid, OBJ_BLOB,
1201
- FSCK_MSG_GITMODULES_PARSE,
1202
- "could not parse gitmodules blob");
1203
-
1204
- return data.ret;
1207
+ return ret;
1208
}
1209
1210
int fsck_object(struct object *obj, void *data, unsigned long size,