Loading accepts a file entry with no hashes #194

Closed
opened 2026-10-12 11:17:37 +02:00 by clawbot · 1 comment
Collaborator

docs/FORMAT.md says a file entry carries at least one hash and that readers validate what they load. deserializeInner in mfer/deserialize.go checks each entry's path and refuses a repeated one, but accepts an entry whose hashes is empty. Such an entry loads; check and fetch then fail it as a hash mismatch, which is safe, but freshen drops it on the way through: addExistingToBuilder in internal/cli/freshen.go returns nil for an unchanged entry with no hashes, so the file silently leaves the rewritten manifest.

Confirmed on next (0fbb3da) with a scratch test: an inner message holding one entry {path: "x", size: 1} and no hashes, wrapped as generate wraps it, comes back from NewManifestFromReader with one entry.

Correct: loading refuses a manifest holding an entry with no hashes, naming the path, as it refuses a bad path; addExistingToBuilder then returns an error for such an entry instead of nil.

Definition of done

  • Failing test first: such a manifest is refused by NewManifestFromReader with a sentinel error.
  • The fix in mfer/deserialize.go; addExistingToBuilder errors instead of dropping the entry.
  • The file entry table in docs/FORMAT.md says readers reject an entry with no hashes.
  • make check passes.

Model: fable-5-1

`docs/FORMAT.md` says a file entry carries at least one hash and that readers validate what they load. `deserializeInner` in `mfer/deserialize.go` checks each entry's path and refuses a repeated one, but accepts an entry whose `hashes` is empty. Such an entry loads; `check` and `fetch` then fail it as a hash mismatch, which is safe, but `freshen` drops it on the way through: `addExistingToBuilder` in `internal/cli/freshen.go` returns nil for an unchanged entry with no hashes, so the file silently leaves the rewritten manifest. Confirmed on `next` (0fbb3da) with a scratch test: an inner message holding one entry `{path: "x", size: 1}` and no hashes, wrapped as `generate` wraps it, comes back from `NewManifestFromReader` with one entry. Correct: loading refuses a manifest holding an entry with no hashes, naming the path, as it refuses a bad path; `addExistingToBuilder` then returns an error for such an entry instead of nil. ## Definition of done - Failing test first: such a manifest is refused by `NewManifestFromReader` with a sentinel error. - The fix in `mfer/deserialize.go`; `addExistingToBuilder` errors instead of dropping the entry. - The file entry table in `docs/FORMAT.md` says readers reject an entry with no hashes. - `make check` passes. Model: fable-5-1
clawbot self-assigned this 2026-10-12 11:17:37 +02:00
Author
Collaborator

Implemented in #202: loading refuses a file entry with no hash, naming its path; freshen errors on one instead of leaving it out; docs/FORMAT.md says readers reject it.

Model: opus-5-5

Implemented in https://git.eeqj.de/sneak/mfer/pulls/202: loading refuses a file entry with no hash, naming its path; `freshen` errors on one instead of leaving it out; `docs/FORMAT.md` says readers reject it. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/mfer#194