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

[PATCH v3 3/4] convert: use size_t for buffer sizes

From
Elia Pinto <gitter.spiros@gmail.com>
Date
Oct 31, 2026, 10:16 UTC
Message-ID
<1617177880b7cbde051bc4295f1fbd6ea2be457b.1793439137.git.gitter.spiros@gmail.com>
In-Reply-To
<cover.1793439137.git.gitter.spiros@gmail.com>

The conversion code receives its buffers with a size_t length, but the helpers that scan them, gather_stats(), gather_convert_stats(), gather_convert_stats_ascii() and count_ident(), take an "unsigned long". On platforms where that is 32 bits wide, like Windows, they only look at the first "size mod 2^32" bytes of a file over 4GiB. The decision whether a file is binary, or contains CRLF line endings or "$Id$" keywords, is then based on that prefix, and we may convert the line endings of a file that is binary further down, or not expand keywords that appear after the first 4GiB.

read_blob_data_from_index(), which feeds has_crlf_in_index(), get_cached_convert_stats_ascii() and the reading of .gitattributes from the index, gets the size of the blob as a size_t, but hands it out through cast_size_t_to_ulong(), so on such platforms "git add" of a file whose staged version is over 4GiB dies when core.autocrlf is in effect.

Use size_t for all of them.
Signed-off-by: Elia Pinto <gitter.spiros@gmail.com>
---
 attr.c          |  2 +-
 convert.c       | 14 +++++++-------
 read-cache-ll.h |  2 +-
 read-cache.c    |  4 ++--
 4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/attr.c b/attr.c
index 0e63f1b6de..1acb4ef430 100644
--- a/attr.c
+++ b/attr.c
@@ -793,7 +793,7 @@ static struct attr_stack *read_attr_from_index(struct index_state *istate,
 {
 	struct attr_stack *stack = NULL;
 	char *buf;
-	unsigned long size;
+	size_t size;
 	int sparse_dir_pos = -1;
 
 	if (!istate)
diff --git a/convert.c b/convert.c
index 036506842c..ca5594cab0 100644
--- a/convert.c
+++ b/convert.c
@@ -42,9 +42,9 @@ struct text_stat {
 	unsigned printable, nonprintable;
 };
 
-static void gather_stats(const char *buf, unsigned long size, struct text_stat *stats)
+static void gather_stats(const char *buf, size_t size, struct text_stat *stats)
 {
-	unsigned long i;
+	size_t i;
 
 	memset(stats, 0, sizeof(*stats));
 
@@ -102,7 +102,7 @@ static int convert_is_binary(const struct text_stat *stats)
 	return 0;
 }
 
-static unsigned int gather_convert_stats(const char *data, unsigned long size)
+static unsigned int gather_convert_stats(const char *data, size_t size)
 {
 	struct text_stat stats;
 	int ret = 0;
@@ -119,7 +119,7 @@ static unsigned int gather_convert_stats(const char *data, unsigned long size)
 	return ret;
 }
 
-static const char *gather_convert_stats_ascii(const char *data, unsigned long size)
+static const char *gather_convert_stats_ascii(const char *data, size_t size)
 {
 	unsigned int convert_stats = gather_convert_stats(data, size);
 
@@ -141,7 +141,7 @@ const char *get_cached_convert_stats_ascii(struct index_state *istate,
 					   const char *path)
 {
 	const char *ret;
-	unsigned long sz;
+	size_t sz;
 	void *data = read_blob_data_from_index(istate, path, &sz);
 	ret = gather_convert_stats_ascii(data, sz);
 	free(data);
@@ -223,7 +223,7 @@ static void check_global_conv_flags_eol(const char *path,
 
 static int has_crlf_in_index(struct index_state *istate, const char *path)
 {
-	unsigned long sz;
+	size_t sz;
 	void *data;
 	const char *crp;
 	int has_crlf = 0;
@@ -1077,7 +1077,7 @@ static int read_convert_config(const char *var, const char *value,
 	return 0;
 }
 
-static int count_ident(const char *cp, unsigned long size)
+static int count_ident(const char *cp, size_t size)
 {
 	/*
 	 * "$Id: 0000000000000000000000000000000000000000 $" <=> "$Id$"
diff --git a/read-cache-ll.h b/read-cache-ll.h
index 066dd8bc3b..d279059b5f 100644
--- a/read-cache-ll.h
+++ b/read-cache-ll.h
@@ -416,7 +416,7 @@ int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
 int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
 void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
 int index_name_is_other(struct index_state *, const char *, int);
-void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
+void *read_blob_data_from_index(struct index_state *, const char *, size_t *);
 
 /* do stat comparison even if CE_VALID is true */
 #define CE_MATCH_IGNORE_VALID		01
diff --git a/read-cache.c b/read-cache.c
index c4cf08a3a3..635dad1ba3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -3472,7 +3472,7 @@ int index_name_is_other(struct index_state *istate, const char *name,
 }
 
 void *read_blob_data_from_index(struct index_state *istate,
-				const char *path, unsigned long *size)
+				const char *path, size_t *size)
 {
 	int pos, len;
 	size_t sz;
@@ -3503,7 +3503,7 @@ void *read_blob_data_from_index(struct index_state *istate,
 		return NULL;
 	}
 	if (size)
-		*size = cast_size_t_to_ulong(sz);
+		*size = sz;
 	return data;
 }
 
-- 
2.53.0
Previous: Elia PintoNext: Elia Pinto
Message 20 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.