Refuse a file entry with no hash when loading a manifest (closes #194)
check / check (push) Waiting to run

Loading accepted a file entry whose hashes list was empty. check and
fetch then failed the file as a hash mismatch, and freshen left it out
of the rewritten manifest without a word.

NewManifestFromReader now refuses such an entry, naming its path, after
checking the path itself. freshen's addExistingToBuilder returns an
error for an entry with no hash instead of skipping it. The file entry
table in docs/FORMAT.md says readers reject an entry with none.

Model: opus-5-5
This commit was merged in pull request #202.
This commit is contained in:
2026-10-13 18:04:47 +02:00
parent f68cc284ac
commit 61238e4071
5 changed files with 66 additions and 14 deletions
+7 -1
View File
@@ -27,6 +27,7 @@ var (
errUUIDMismatch = errors.New("outer and inner UUID mismatch")
errInvalidFileFormat = errors.New("invalid file format")
errInvalidManifestPath = errors.New("invalid file entry")
errEntryMissingHash = errors.New("file entry has no hash")
errDecodedTooLarge = errors.New("too much memory needed")
errSignerNotSigningKey = errors.New(
"signer is not the fingerprint of the key that made the signature")
@@ -293,7 +294,8 @@ func (m *manifest) deserializeInner() error {
// untrusted .mf. Reject loudly on the first offender rather than
// dropping entries, which would let a hostile manifest hide files from a
// check. A path listed twice is refused too: check would check the one
// file against both entries.
// file against both entries. So is an entry with no hash: there is
// nothing to check the file against.
seen := make(map[string]bool, len(m.pbInner.GetFiles()))
for _, f := range m.pbInner.GetFiles() {
@@ -302,6 +304,10 @@ func (m *manifest) deserializeInner() error {
return fmt.Errorf("%w: %w", errInvalidManifestPath, err)
}
if len(f.GetHashes()) == 0 {
return fmt.Errorf("%w: %q", errEntryMissingHash, f.GetPath())
}
if seen[f.GetPath()] {
return fmt.Errorf("%w %q", errDuplicatePath, f.GetPath())
}