From: Elia Pinto Date: Fri, 30 Oct 2026 10:28:37 GMT Subject: [PATCH 4/6] cat-file: use size_t for the length passed to batch_write() Message-ID: In-Reply-To: batch_write() takes the length of the data as an "int", but its callers pass the size of whole objects as returned by odb_read_object() or filter_object(), which is a size_t. For an object between 2GiB and 4GiB the length wraps to a negative value, which fwrite() and write_or_die() then see as an enormous size_t. We happily write the object and then keep going past the end of the buffer, sending whatever memory follows to stdout, until we hit an unmapped page and die with "write error: Bad address". Objects of 4GiB and more are truncated instead, which desynchronizes the --batch output. This affects all platforms, not only those with a 32-bit "long". It can be triggered with "--batch" on any non-blob object, or on blobs with --filters or --textconv, as blobs are otherwise streamed. For example: blob=$(test-tool genzeros $((3 * 1024 * 1024 * 1024)) | git hash-object -w --stdin) && echo "$blob big" | git cat-file --batch="%(objectname) %(rest)" --filters >out fails with "write error: Bad address"; with stdout going to /dev/null, strace shows write() being called on addresses far beyond the end of the 3GiB buffer. There is no test, as it would need several GiB of memory and disk. Both fwrite() and write_or_die() take a size_t already, so just change the parameter type. Signed-off-by: Elia Pinto --- builtin/cat-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 8870a210ec..c846fe3116 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -425,7 +425,7 @@ static void expand_format(struct strbuf *sb, const char *start, } } -static void batch_write(struct batch_options *opt, const void *data, int len) +static void batch_write(struct batch_options *opt, const void *data, size_t len) { if (opt->buffer_output) { if (fwrite(data, 1, len, stdout) != len) -- 2.53.0