From 7a15e83449a494bee01209e5740eb43a69db7021 Mon Sep 17 00:00:00 2001 From: Tim Kientzle Date: Sat, 28 Jun 2025 14:11:17 -0700 Subject: [PATCH] Merge pull request #2688 from stoeckmann/entry_off32 Ignore sizes which do not fit into off_t (cherry picked from commit a474bab7e381e4d54dc336b8206060e64b81cffd) --- libarchive/archive_entry_stat.c | 6 +++++- libarchive/archive_windows.c | 2 ++ libarchive/test/test_entry.c | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libarchive/archive_entry_stat.c b/libarchive/archive_entry_stat.c index c4906838e..345d3d29b 100644 --- a/libarchive/archive_entry_stat.c +++ b/libarchive/archive_entry_stat.c @@ -38,6 +38,7 @@ const struct stat * archive_entry_stat(struct archive_entry *entry) { + int64_t size; struct stat *st; if (entry->stat == NULL) { entry->stat = calloc(1, sizeof(*st)); @@ -74,7 +75,10 @@ archive_entry_stat(struct archive_entry *entry) st->st_ino = (ino_t)archive_entry_ino64(entry); st->st_nlink = archive_entry_nlink(entry); st->st_rdev = archive_entry_rdev(entry); - st->st_size = (off_t)archive_entry_size(entry); + size = archive_entry_size(entry); + st->st_size = (off_t)size; + if (st->st_size < 0 || (int64_t)st->st_size != size) + st->st_size = 0; st->st_mode = archive_entry_mode(entry); /* diff --git a/libarchive/archive_windows.c b/libarchive/archive_windows.c index 0ccea0f81..19180bba6 100644 --- a/libarchive/archive_windows.c +++ b/libarchive/archive_windows.c @@ -561,6 +561,8 @@ copy_stat(struct stat *st, struct ustat *us) st->st_mode = us->st_mode; st->st_nlink = us->st_nlink; st->st_size = (off_t)us->st_size; + if (st->st_size < 0 || (uint64_t)st->st_size != us->st_size) + st->st_size = 0; st->st_uid = us->st_uid; st->st_dev = us->st_dev; st->st_rdev = us->st_rdev; diff --git a/libarchive/test/test_entry.c b/libarchive/test/test_entry.c index 9b21b83ec..cff9c5c86 100644 --- a/libarchive/test/test_entry.c +++ b/libarchive/test/test_entry.c @@ -880,6 +880,17 @@ DEFINE_TEST(test_entry) if (pst == NULL) return; assertEqualInt(pst->st_uid, 22); + + /* Check behavior with large sizes. */ + archive_entry_set_size(e, INT64_MAX - 1); + assert((pst = archive_entry_stat(e)) != NULL); + if (pst == NULL) + return; + if (sizeof(pst->st_size) < sizeof(int64_t)) + assertEqualInt(pst->st_size, 0); + else + assertEqualInt(pst->st_size, INT64_MAX - 1); + /* We don't need to check high-res fields here. */ /* -- 2.47.3