From b3a1a9e654d62363e23dfd9dc351fc00520e85e3 Mon Sep 17 00:00:00 2001 From: DanS Date: Tue, 13 Oct 2026 20:57:21 -0500 Subject: [PATCH] fix(bootstrap): report verify progress correctly past 2 GiB The checksum and MD5 passes measured the file for their progress bar with fseek/ftell. On Windows a long is 32-bit, so ftell overflows on any archive larger than 2 GiB and hands back a wrong (often negative) size, which makes the verify progress percentage meaningless on exactly the multi-gigabyte downloads this code exists for. - Both passes now take the size from std::filesystem::file_size, which is 64-bit on every platform, through a small helper that returns 0 if the size can't be read. - No seek is performed just to size the file. Co-Authored-By: Claude Opus 4.8 --- src/util/bootstrap.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/util/bootstrap.cpp b/src/util/bootstrap.cpp index b5b018e..66fbde0 100644 --- a/src/util/bootstrap.cpp +++ b/src/util/bootstrap.cpp @@ -116,6 +116,13 @@ static std::uint64_t satAdd(std::uint64_t a, std::uint64_t b) { return (a > UINT64_MAX - b) ? UINT64_MAX : a + b; } +// fs::file_size is 64-bit on every platform; ftell() returns a 32-bit long on Win LLP64. +static long long fileSizeOrZero(const std::string& path) { + std::error_code ec; + auto sz = fs::file_size(path, ec); + return ec ? 0 : (long long)sz; +} + static std::string lowerAscii(std::string s) { for (char& c : s) if (c >= 'A' && c <= 'Z') c = static_cast(c - 'A' + 'a'); @@ -924,10 +931,8 @@ std::string Bootstrap::computeSHA256(const std::string& filePath, float pctBase, FILE* fp = fopen(filePath.c_str(), "rb"); if (!fp) return {}; - // Get file size for progress reporting - fseek(fp, 0, SEEK_END); - long long fileSize = ftell(fp); - fseek(fp, 0, SEEK_SET); + // File size for progress reporting (not a seek: ftell is 32-bit on Windows LLP64). + const long long fileSize = fileSizeOrZero(filePath); crypto_hash_sha256_state state; crypto_hash_sha256_init(&state); @@ -1061,10 +1066,8 @@ std::string Bootstrap::computeMD5(const std::string& filePath, float pctBase, fl FILE* fp = fopen(filePath.c_str(), "rb"); if (!fp) return {}; - // Get file size for progress reporting - fseek(fp, 0, SEEK_END); - long long fileSize = ftell(fp); - fseek(fp, 0, SEEK_SET); + // File size for progress reporting (not a seek: ftell is 32-bit on Windows LLP64). + const long long fileSize = fileSizeOrZero(filePath); MD5Context ctx; md5_init(&ctx);