[PATCH 2/3] diff: use size_t for the allocation size of word-diff buffers
- From
Elia Pinto <gitter.spiros@gmail.com>
- Date
- Oct 21, 2026, 10:16 UTC
- Message-ID
- <20261021101640.329990-3-gitter.spiros@gmail.com>
- In-Reply-To
- <20261021101640.329990-1-gitter.spiros@gmail.com>
Since 3c7a31204f (xdiff: use size_t for buffer sizes, 2026-09-30) the size of an mmfile_t is a size_t, but the word-diff code still grows these buffers with ALLOC_GROW() using an "unsigned long" (in struct diff_words_buffer) or a "long" (in diff_words_fill()) for the allocated size.
On platforms where "long" is 32 bits wide this is not just cosmetic. diff_words_fill() writes every word followed by a newline, so its output can be up to twice as large as its input, which is limited by MAX_XDIFF_SIZE to just under 1GiB. alloc_nr() computes (alloc + 16) * 3 in the type of "alloc", which overflows a signed 32-bit "long" as soon as the buffer grows past about 700MiB. The result is undefined behavior, in practice a negative size that REALLOC_ARRAY() turns into a huge allocation request and a die().
The buffer in diff_words_append() is bounded by MAX_XDIFF_SIZE, so there it is only a matter of consistency, but if that limit ever went away, ALLOC_GROW() would truncate the requested size, and the memcpy() right after it would overflow the buffer.
Use size_t for both.
Signed-off-by: Elia Pinto <gitter.spiros@gmail.com> --- diff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/diff.c b/diff.c index b4ac17f8ef..9483931c05 100644 --- a/diff.c +++ b/diff.c @@ -1959,7 +1959,7 @@ static void emit_rewrite_diff(const char *name_a, struct diff_words_buffer { mmfile_t text; - unsigned long alloc; + size_t alloc; struct diff_words_orig { const char *begin, *end; } *orig; @@ -2192,7 +2192,7 @@ static void diff_words_fill(struct diff_words_buffer *buffer, mmfile_t *out, regex_t *word_regex) { int i, j; - long alloc = 0; + size_t alloc = 0; out->size = 0; out->ptr = NULL;
-- 2.53.0