1 Commits
Author SHA1 Message Date
clawbot e2deea2e34 Drop mimeType and ctime from the manifest format (closes #235)
check / check (push) Waiting to run
Nothing goes in the 1.0 manifest that 1.0 does not read or write, and
mfer never wrote either field. mf.proto now reserves the numbers 301 and
303 and both names in MFFilePath, and mf.pb.go is regenerated. The
decoded-size check counts only file entries, hashes and timestamps, and
counts a file entry, 16 bytes smaller without the two fields, at 160
bytes. export prints no ctime, and FileEntry loses the Ctime nothing
set. FORMAT.md and the README no longer describe either field.

The test of entries that decode too large gives each entry a second,
empty hash: an entry with one hash and a modification time can no
longer reach 8 times its size.

Model: opus-5-5
2026-10-19 20:52:00 +02:00
3 changed files with 12 additions and 12 deletions
+1 -1
View File
@@ -61,7 +61,7 @@ enforce a decompression size limit to prevent decompression bombs. The reference
implementation limits decompressed size to 256 MiB. It writes zstd frames with a
window of at most 8 MiB, the largest window the zstd format recommends decoders
support, and refuses frames that ask for a larger one. It also refuses an inner
message whose file entries, hashes and timestamps, counted at 176, 112 and 64
message whose file entries, hashes and timestamps, counted at 160, 112 and 64
bytes each, add up to more than 8 times its size. It refuses a manifest file
larger than 258 MiB without reading the rest of it: zstd's worst case grows a
256 MiB inner message by 1/256 to 257 MiB, and the last MiB is room for the
+3 -3
View File
@@ -29,14 +29,14 @@ const (
// however short its encoding. checkDecodedSize refuses an inner
// message for which these add up to more than maxDecodedGrowth times
// its size. The mode is held in the file entry itself.
decodedFileEntrySize = 176
decodedFileEntrySize = 160
decodedHashSize = 112
decodedTimestampSize = 64
// Each file entry mfer writes holds a path of at least one byte, a
// multihash at least as long as SHA-256's 34 bytes (AddFileWithHash
// refuses shorter ones) and a modification time: at least 47 bytes,
// counted at 352. So its manifests add up to at most about 7.49 times
// their size, and this limit is about 7% above that.
// counted at 336. So its manifests add up to at most about 7.15 times
// their size, and this limit is about 12% above that.
maxDecodedGrowth = 8
)
+8 -8
View File
@@ -296,13 +296,13 @@ func TestDeserializeRefusesModeOutsidePermissionBits(t *testing.T) {
}
// Entries of a path, a SHA-256 hash, an empty second hash and an empty
// modification time are counted at 464 bytes each (176 + 112 + 112 + 64)
// and take 48 bytes plus the path to encode. A 9-character path makes that
// 57 bytes, about 8.1 times: refused, and leaving any one of the four
// uncounted, even the modification time, brings it under 8. A 10-character
// path makes it 58 bytes, 8 times exactly: loaded. Without the second hash
// modification time are counted at 448 bytes each (160 + 112 + 112 + 64)
// and take 48 bytes plus the path to encode. A 7-character path makes that
// 55 bytes, about 8.1 times: refused, and leaving any one of the four
// uncounted, even the modification time, brings it under 8. An 8-character
// path makes it 56 bytes, 8 times exactly: loaded. Without the second hash
// an entry is never refused: it takes at least 47 bytes and is counted at
// 352. There is one entry for each base-36 digit, enough that the 22 bytes
// 336. There is one entry for each base-36 digit, enough that the 22 bytes
// of the version and UUID change neither outcome, and each entry's path is
// its number in base 36, padded with zeros to that length, since a manifest
// lists a path only once.
@@ -319,8 +319,8 @@ func TestDeserializeRefusesEntriesThatDecodeTooLarge(t *testing.T) {
pathLen int
refused bool
}{
{9, true},
{10, false},
{7, true},
{8, false},
}
for _, tt := range tests {