1 Commits
Author SHA1 Message Date
clawbot 0c3b342329 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,
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 18:20:43 +00: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 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 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 support, and refuses frames that ask for a larger one. It also refuses an inner
message whose file entries, hashes and timestamps, counted at 160, 112 and 64 message whose file entries, hashes and timestamps, counted at 176, 112 and 64
bytes each, add up to more than 8 times its size. It refuses a manifest file 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 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 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 // however short its encoding. checkDecodedSize refuses an inner
// message for which these add up to more than maxDecodedGrowth times // message for which these add up to more than maxDecodedGrowth times
// its size. The mode is held in the file entry itself. // its size. The mode is held in the file entry itself.
decodedFileEntrySize = 160 decodedFileEntrySize = 176
decodedHashSize = 112 decodedHashSize = 112
decodedTimestampSize = 64 decodedTimestampSize = 64
// Each file entry mfer writes holds a path of at least one byte, a // 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 // multihash at least as long as SHA-256's 34 bytes (AddFileWithHash
// refuses shorter ones) and a modification time: at least 47 bytes, // refuses shorter ones) and a modification time: at least 47 bytes,
// counted at 336. So its manifests add up to at most about 7.15 times // counted at 352. So its manifests add up to at most about 7.49 times
// their size, and this limit is about 12% above that. // their size, and this limit is about 7% above that.
maxDecodedGrowth = 8 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 // Entries of a path, a SHA-256 hash, an empty second hash and an empty
// modification time are counted at 448 bytes each (160 + 112 + 112 + 64) // modification time are counted at 464 bytes each (176 + 112 + 112 + 64)
// and take 48 bytes plus the path to encode. A 7-character path makes that // and take 48 bytes plus the path to encode. A 9-character path makes that
// 55 bytes, about 8.1 times: refused, and leaving any one of the four // 57 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 // uncounted, even the modification time, brings it under 8. A 10-character
// path makes it 56 bytes, 8 times exactly: loaded. Without the second hash // path makes it 58 bytes, 8 times exactly: loaded. Without the second hash
// an entry is never refused: it takes at least 47 bytes and is counted at // an entry is never refused: it takes at least 47 bytes and is counted at
// 336. There is one entry for each base-36 digit, enough that the 22 bytes // 352. 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 // 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 // its number in base 36, padded with zeros to that length, since a manifest
// lists a path only once. // lists a path only once.
@@ -319,8 +319,8 @@ func TestDeserializeRefusesEntriesThatDecodeTooLarge(t *testing.T) {
pathLen int pathLen int
refused bool refused bool
}{ }{
{7, true}, {9, true},
{8, false}, {10, false},
} }
for _, tt := range tests { for _, tt := range tests {