diff options
context:
space:
mode:
authorBryce Kwon <bryce@brycekwon.com>
committerBryce Kwon <bryce@brycekwon.com>
commit
parent
tree
download
Cap diff blobs by `max-blob-size`
The diff family inflated a blob of any size just to render it. A file over the limit is reported as binary instead.
Diffstat (limited to 'source')
-rw-r--r--source/shared.c25
1 file changed, 22 insertions, 3 deletions
diff --git a/source/shared.c b/source/shared.c
index 24f9c3c..59f1c8e 100644
--- a/source/shared.c
+++ b/source/shared.c
@@ -311,12 +311,31 @@ int cgit_diff_files(const struct object_id *old_oid,
xpparam_t diff_params;
xdemitconf_t emit_params;
xdemitcb_t emit_cb;
+ unsigned long size1 = 0, size2 = 0;
- if (!load_mmfile(&file1, old_oid) || !load_mmfile(&file2, new_oid))
+ // Read the object headers first so an oversized blob is never
+ // inflated into memory just to be diffed. Report it as binary,
+ // which suppresses inlining the same way max-blob-size does for
+ // the blob, plain and tree views.
+ if (!is_null_oid(old_oid) &&
+ odb_read_object_info(the_repository->objects, old_oid, &size1) < 0)
+ return 1;
+ if (!is_null_oid(new_oid) &&
+ odb_read_object_info(the_repository->objects, new_oid, &size2) < 0)
return 1;
- *old_size = file1.size;
- *new_size = file2.size;
+ *old_size = size1;
+ *new_size = size2;
+
+ if (ctx.cfg.max_blob_size &&
+ (size1 / 1024 > (unsigned long)ctx.cfg.max_blob_size ||
+ size2 / 1024 > (unsigned long)ctx.cfg.max_blob_size)) {
+ *binary = 1;
+ return 0;
+ }
+
+ if (!load_mmfile(&file1, old_oid) || !load_mmfile(&file2, new_oid))
+ return 1;
if ((file1.ptr && buffer_is_binary(file1.ptr, file1.size)) ||
(file2.ptr && buffer_is_binary(file2.ptr, file2.size))) {