]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: teach read_blob_entry to use size_t
authorMatt Cooper <vtbassmatt@gmail.com>
Tue, 2 Nov 2021 15:46:08 +0000 (15:46 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Nov 2021 18:22:27 +0000 (11:22 -0700)
There is mixed use of size_t and unsigned long to deal with sizes in the
codebase. Recall that Windows defines unsigned long as 32 bits even on
64-bit platforms, meaning that converting size_t to unsigned long narrows
the range. This mostly doesn't cause a problem since Git rarely deals
with files larger than 2^32 bytes.

But adjunct systems such as Git LFS, which use smudge/clean filters to
keep huge files out of the repository, may have huge file contents passed
through some of the functions in entry.c and convert.c. On Windows, this
results in a truncated file being written to the workdir. I traced this to
one specific use of unsigned long in write_entry (and a similar instance
in write_pc_item_to_fd for parallel checkout). That appeared to be for
the call to read_blob_entry, which expects a pointer to unsigned long.

By altering the signature of read_blob_entry to expect a size_t,
write_entry can be switched to use size_t internally (which all of its
callers and most of its callees already used). To avoid touching dozens of
additional files, read_blob_entry uses a local unsigned long to call a
chain of functions which aren't prepared to accept size_t.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Matt Cooper <vtbassmatt@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
entry.c
entry.h
parallel-checkout.c
t/t1051-large-conversion.sh

diff --git a/entry.c b/entry.c
index 711ee0693c75433635dc73bc98eda88ca6e1bc3f..4cb3942dbdcb0ce596a9829c1b6219f306be8724 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -82,11 +82,13 @@ static int create_file(const char *path, unsigned int mode)
        return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
 }
 
-void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
+void *read_blob_entry(const struct cache_entry *ce, size_t *size)
 {
        enum object_type type;
-       void *blob_data = read_object_file(&ce->oid, &type, size);
+       unsigned long ul;
+       void *blob_data = read_object_file(&ce->oid, &type, &ul);
 
+       *size = ul;
        if (blob_data) {
                if (type == OBJ_BLOB)
                        return blob_data;
@@ -270,7 +272,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
        int fd, ret, fstat_done = 0;
        char *new_blob;
        struct strbuf buf = STRBUF_INIT;
-       unsigned long size;
+       size_t size;
        ssize_t wrote;
        size_t newsize = 0;
        struct stat st;
diff --git a/entry.h b/entry.h
index b8c0e170dc791a7bebde1e6e71c194f3301a9cff..61ee8c17604180e6efb731c11fd14c12f1b46f45 100644 (file)
--- a/entry.h
+++ b/entry.h
@@ -51,7 +51,7 @@ int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
  */
 void unlink_entry(const struct cache_entry *ce);
 
-void *read_blob_entry(const struct cache_entry *ce, unsigned long *size);
+void *read_blob_entry(const struct cache_entry *ce, size_t *size);
 int fstat_checkout_output(int fd, const struct checkout *state, struct stat *st);
 void update_ce_after_write(const struct checkout *state, struct cache_entry *ce,
                           struct stat *st);
index 6b1af32bb3d4f7fc52db1ccf1bbda46ccda95fa4..b6f4a25642e43c1a286e8530502bb07d9d124ba6 100644 (file)
@@ -261,7 +261,7 @@ static int write_pc_item_to_fd(struct parallel_checkout_item *pc_item, int fd,
        struct stream_filter *filter;
        struct strbuf buf = STRBUF_INIT;
        char *blob;
-       unsigned long size;
+       size_t size;
        ssize_t wrote;
 
        /* Sanity check */
index e7f9f0bdc567d63b9fd0ade3acfeabf55c650271..e6d52f98b15657157999b26f721e3b65790ed71a 100755 (executable)
@@ -85,7 +85,7 @@ test_expect_success 'ident converts on output' '
 
 # This smudge filter prepends 5GB of zeros to the file it checks out. This
 # ensures that smudging doesn't mangle large files on 64-bit Windows.
-test_expect_failure EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \
+test_expect_success EXPENSIVE,SIZE_T_IS_64BIT,!LONG_IS_64BIT \
                'files over 4GB convert on output' '
        test_commit test small "a small file" &&
        small_size=$(test_file_size small) &&