Skip to content

fix(updater): reject zero-byte staged binary + error on oversized archive#2

Merged
TeoSlayer merged 1 commit into
mainfrom
fix-replace-binary-empty-src-and-truncation
May 28, 2026
Merged

fix(updater): reject zero-byte staged binary + error on oversized archive#2
TeoSlayer merged 1 commit into
mainfrom
fix-replace-binary-empty-src-and-truncation

Conversation

@TeoSlayer
Copy link
Copy Markdown
Contributor

Summary

Two real bugs in updater.go that would surface as silent corruption / confusing operator errors.

Bug 1 (HIGH, operational): replaceBinary would brick the daemon on a zero-byte staged binary

replaceBinary did not validate that src was non-empty before os.Rename. A zero-byte staged binary atomic-renamed over the live daemon binary would brick the daemon on the next start. Now stats src first and refuses with "refusing to replace binary with empty source: <path>" — the existing binary keeps running, the operator sees the update failed loudly.

Bug 2 (MED, UX): downloadFile silently truncated oversize archives

io.LimitReader(resp.Body, maxDownloadBytes) quietly capped the body at 256 MiB. The downloaded file became a corrupt prefix and the subsequent SHA256 check failed with "checksum mismatch" — the operator had no clue the real problem was archive size. Now reads one byte past the cap and returns "archive exceeds max download size %d bytes" explicitly.

Test plan

  • TestReplaceBinary_RejectsEmptySource — zero-byte src + non-empty dst; expect error, dst untouched, no .new scratch left behind.
  • TestDownloadRejectsOversizedArchivehttptest.NewServer streams maxDownloadBytes + 1 KiB; expect explicit "exceeds max download size" error, and assert the error does NOT mention "checksum".
  • go test -race -count=1 -timeout 120s ./... passes.

…hive

replaceBinary previously called os.Rename on src without checking its size,
so a 0-byte staged binary would atomic-rename over the live daemon binary
and brick the daemon on next start. Refuse explicitly when the source is
empty so the existing binary keeps running.

downloadFile capped the body at maxDownloadBytes via io.LimitReader, which
silently truncated oversize archives. The SHA256 check then failed with a
confusing "checksum mismatch" instead of telling the operator the archive
was too large. Read one byte past the cap and surface a clear "archive
exceeds max download size" error.

Adds TestReplaceBinary_RejectsEmptySource and TestDownloadRejectsOversizedArchive
as regressions for both paths.
@TeoSlayer TeoSlayer merged commit e8ef679 into main May 28, 2026
1 check passed
@TeoSlayer TeoSlayer deleted the fix-replace-binary-empty-src-and-truncation branch May 28, 2026 01:23
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants