perf(updater): read the downloaded archive in one bounded allocation

Before verifying a downloaded archive, both updaters slurped it into a
string with an istreambuf_iterator, which grows the buffer repeatedly
and reallocates as it reads a multi-megabyte file. It also placed no
upper bound on the size it would read into memory.

- A shared readFileExact helper sizes the file first and reads it in a
  single allocation, failing closed if the file is missing, empty,
  larger than a caller-supplied cap, or comes up short. A truncated read
  can never reach the SHA-256 / signature verifier.
- Both updaters use it with the existing max-archive cap.

Tests cover a good read, a read exactly at the cap, over the cap, an
empty file, and a missing file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-13 22:03:00 -05:00
co-authored by Claude Opus 4.8
parent e685d425ed
commit 8168e26d93
5 changed files with 58 additions and 16 deletions
+33
View File
@@ -18413,12 +18413,45 @@ void testMigrationWantsBalanceScan()
EXPECT_FALSE(migrationWantsBalanceScan(false, true, 1, -1.0)); // syncing defers the automatic scan
}
void testReadFileExact()
{
namespace fs = std::filesystem;
const fs::path dir = fs::temp_directory_path() / "dragonx_readfileexact_test";
std::error_code ec;
fs::create_directories(dir, ec);
const std::string good = (dir / "good.bin").string();
const std::string empty = (dir / "empty.bin").string();
std::string payload;
for (int i = 0; i < 1000; ++i) payload.push_back(static_cast<char>(i % 251));
payload.push_back('\0');
{ std::ofstream o(good, std::ios::binary); o.write(payload.data(), static_cast<std::streamsize>(payload.size())); }
{ std::ofstream o(empty, std::ios::binary); }
std::string out = "stale";
EXPECT_TRUE(dragonx::util::readFileExact(good, out, 1 << 20));
EXPECT_TRUE(out == payload);
EXPECT_TRUE(dragonx::util::readFileExact(good, out, payload.size())); // exactly at the cap
EXPECT_TRUE(out == payload);
out = "stale";
EXPECT_FALSE(dragonx::util::readFileExact(good, out, payload.size() - 1)); // over the cap
EXPECT_TRUE(out.empty());
out = "stale";
EXPECT_FALSE(dragonx::util::readFileExact(empty, out, 1 << 20));
EXPECT_TRUE(out.empty());
out = "stale";
EXPECT_FALSE(dragonx::util::readFileExact((dir / "missing.bin").string(), out, 1 << 20));
EXPECT_TRUE(out.empty());
fs::remove_all(dir, ec);
}
int main()
{
testConnectionConfig();
testClassifyRpcFailure();
testClassifyUnlockFailure();
testHttpSinkAccept();
testReadFileExact();
testSecureWipeAndRemove();
testFormatHttpError();
testRpcFailureKindOf();