Refuse a path listed twice in a manifest (closes #170)
check / check (push) Canceled after 0s

gen given arguments whose files share a path, such as gen a b with a.txt
in both, or gen . ., now fails while listing the files, before hashing
any, naming the path and both files. Builder.AddFile and
Builder.AddFileWithHash refuse a path already added. Loading refuses a
manifest that lists a path twice, compared byte for byte; fetch keeps
its own letter-case check. The Path Rules in docs/FORMAT.md say each
path appears at most once. The decode-size test listed one path 1000
times; each entry now has its own path of the same length.

Model: opus-5-5
This commit was merged in pull request #174.
This commit is contained in:
2026-10-07 15:28:57 +02:00
parent 01ff67a38e
commit 4fe1ff2fe1
7 changed files with 181 additions and 29 deletions
+10 -1
View File
@@ -298,12 +298,21 @@ func (m *manifest) deserializeInner() error {
// extract path tomorrow — acts on a traversal or absolute path from an
// untrusted .mf. Reject loudly on the first offender rather than
// dropping entries, which would let a hostile manifest hide files from a
// check.
// check. A path listed twice is refused too: check would check the one
// file against both entries.
seen := make(map[string]bool, len(m.pbInner.GetFiles()))
for _, f := range m.pbInner.GetFiles() {
err = ValidatePath(f.GetPath())
if err != nil {
return fmt.Errorf("%w: %w", errInvalidManifestPath, err)
}
if seen[f.GetPath()] {
return fmt.Errorf("%w %q", errDuplicatePath, f.GetPath())
}
seen[f.GetPath()] = true
}
log.Infof("loaded manifest with %d files", len(m.pbInner.GetFiles()))