git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 0/3] use size_t for a few more object and buffer sizes

From
Elia Pinto <gitter.spiros@gmail.com>
Date
Oct 21, 2026, 10:16 UTC
Message-ID
<20261021101640.329990-1-gitter.spiros@gmail.com>

On 64-bit Windows, "long" is still 32 bits wide. Whenever a size_t travels through an "unsigned long", anything above 4 GiB is silently lost. Johannes's js/objects-larger-than-4gb-on-windows work fixed the read side of the object database, and Peff's jk/xdiff-size_t did the same for the diff and merge machinery. This series picks up three places that were left narrow.

 - odb: the write API still takes the object length as unsigned long.
   A large file that is converted before being stored (for example
   with core.autocrlf, which Git for Windows enables by default) can
   reach odb_write_object() with a size_t length above 4 GiB. The
   blob is then written truncated, with no error, and the index
   happily records it.
 - diff: diff_words_fill() grows its buffer with a signed "long"
   allocation size. Its output can be twice its input, and on LLP64
   the growth computation overflows past about 700MiB, which is well
   within what xdiff accepts. In practice Git dies on a huge
   allocation request.
 - convert: the helpers that decide whether a file is binary, has
   CRLF line endings or "$Id$" keywords take an unsigned long length.
   For files over 4GiB they only look at a prefix. In the same area,
   read_blob_data_from_index() narrows its result with
   cast_size_t_to_ulong(), so "git add" with core.autocrlf dies when
   the staged version is that large.

There are no new tests. Each case needs files of several GiB and a 32-bit "long", and the commit messages explain how to reproduce them.

How these were found --------------------

I wanted a list of all the places where a 64-bit size is narrowed on Windows, rather than waiting for the next bug report. Linux compilers cannot see the problem, because there "long" and "size_t" have the same width. So I analysed the tree as a Windows target instead.

The first step is a compilation database from a real MinGW configuration. Forcing --target onto a database generated on Linux does not work well: Linux-only defines leak in, regex.h is missing from MinGW, and the precompiled header is rejected for the wrong target. A Meson cross build avoids all of that:

  $ cat mingw64.cross
  [binaries]
  c       = 'x86_64-w64-mingw32-gcc'
  ar      = 'x86_64-w64-mingw32-ar'
  strip   = 'x86_64-w64-mingw32-strip'
  windres = 'x86_64-w64-mingw32-windres'
  [host_machine]
  system     = 'windows'
  cpu_family = 'x86_64'
  cpu        = 'x86_64'
  endian     = 'little'
  $ meson setup build-win --cross-file mingw64.cross \
	-Db_pch=false -Dsane_tool_path=/usr/bin \
	-Dcurl=disabled -Dexpat=disabled -Dpcre2=disabled \
	-Dgettext=disabled -Diconv=disabled -Drust=disabled
  $ meson compile -C build-win

Two of these options are not obvious. Without -Dsane_tool_path, setup stops because meson.build adds "C:/Program Files/Git/bin" to the program search path, which is not absolute on a Linux host. And -Db_pch=false is needed because clang cannot read the precompiled header that GCC produces. The build only has to get far enough to generate the headers; link errors do not matter here.

The second step runs clang-tidy over that database with -Wshorten-64-to-32, for the x86_64-w64-mingw32 target, skipping the bundled zlib and OpenSSL. One detail cost me a while: with "-checks=-*", clang-tidy drops compiler warnings unless clang-diagnostic-shorten-64-to-32 is enabled explicitly. I wrapped all this in a small script, which also refuses to report "no findings" when some translation units failed to parse:

  https://github.com/devzero2000/toyscript/blob/main/check_llp64_portability.sh

It is not meant for inclusion. I mention it so that the numbers below can be reproduced, and in case someone finds it useful.

What the scan shows -------------------

All 569 translation units were analysed, none failed. There are 1432
64-to-32 truncation warnings, but most of them are not specific to
Windows: about 1200 narrow a size_t to an int, as they do on Linux.
Only 237 have "long" or "unsigned long" as their destination.

Most of those 237 sit on API boundaries that are known and that commit c6a4629e32 names explicitly: diff, blame, textconv and fast-import. Others are in tree walking, object parsing and the pack tools, where an oversized object makes Git die rather than misbehave. I would like to convert them in later small series, one area at a time, in the same style as jk/xdiff-size_t.

Johannes, the first patch continues your write-side work. I hope it does not step on a follow-up you already have in progress.

Elia Pinto (3):
  odb: use size_t for the length of objects to write
  diff: use size_t for the allocation size of word-diff buffers
  convert: use size_t for buffer sizes
 attr.c                |  2 +-
 convert.c             | 14 +++++++-------
 diff.c                |  4 ++--
 odb.c                 |  2 +-
 odb.h                 |  4 ++--
 odb/source-inmemory.c |  2 +-
 odb/source-loose.c    |  2 +-
 odb/source.h          |  2 +-
 read-cache-ll.h       |  2 +-
 read-cache.c          |  4 ++--
 10 files changed, 19 insertions(+), 19 deletions(-)

base-commit: 47fdf2208c5b94c8cc01c106b8f7c85efb91c926 -- 2.53.0

Next: Elia Pinto
Message 1 of 21 in “use size_t for a few more object and buffer sizes”
  1. 0/3 use size_t for a few more object and buffer sizesElia Pinto, Oct 21, 2026
  2. 1/3 odb: use size_t for the length of objects to writeElia Pinto, Oct 21, 2026
  3. Patrick SteinhardtOct 21, 2026
  4. 2/3 diff: use size_t for the allocation size of word-diff buffersElia Pinto, Oct 21, 2026
  5. Patrick SteinhardtOct 21, 2026
  6. 3/3 convert: use size_t for buffer sizesElia Pinto, Oct 21, 2026
  7. Patrick SteinhardtOct 21, 2026
  8. 0/4 use size_t for a few more object and buffer sizesElia Pinto, Oct 30, 2026
  9. 1/4 odb: use size_t for the length of objects to writeElia Pinto, Oct 30, 2026
  10. Patrick SteinhardtOct 30, 2026
  11. Elia PintoOct 31, 2026
  12. 2/4 diff: use size_t for the allocation size of word-diff buffersElia Pinto, Oct 30, 2026
  13. 3/4 convert: use size_t for buffer sizesElia Pinto, Oct 30, 2026
  14. 4/4 convert: use size_t for text statistics and ident countsElia Pinto, Oct 30, 2026
  15. Patrick SteinhardtOct 30, 2026
  16. Elia PintoOct 31, 2026
  17. 0/4 use size_t for a few more object and buffer sizesElia Pinto, Oct 31, 2026
  18. 1/4 odb: use size_t for the length of objects to writeElia Pinto, Oct 31, 2026
  19. 2/4 diff: use size_t for the allocation size of word-diff buffersElia Pinto, Oct 31, 2026
  20. 3/4 convert: use size_t for buffer sizesElia Pinto, Oct 31, 2026
  21. 4/4 convert: use size_t for text statistics and ident countsElia Pinto, Oct 31, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.