Refuse a manifest entry whose mode is above 0777 on load (closes #225)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Loading accepted an entry recording a mode above 0777, such as 04755. check then reported a file with exactly the recorded permission bits as a mode mismatch, list and export printed the out-of-range mode, and freshen silently rewrote it as the permission bits alone. Loading now refuses such an entry, naming the path and the mode, so every command that reads a manifest refuses it with one message. fetch's own check for this could no longer be reached and is gone; its test moves to the loading tests in package mfer. docs/FORMAT.md says readers reject a mode above 0777. Model: opus-5-5
This commit was merged in pull request #230.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -234,6 +235,66 @@ func TestDeserializeRequiresExactlyOneSHA256Hash(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// A file entry that records a mode with more than the permission bits is
|
||||
// refused as it is loaded, naming the path and the mode: once with setuid as
|
||||
// Unix writes it (04755) and once as Go keeps it in os.FileMode. An entry
|
||||
// recording 0777 loads.
|
||||
func TestDeserializeRefusesModeOutsidePermissionBits(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
hash, err := multihash.Encode(make([]byte, sha256.Size), multihash.SHA2_256)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mode uint32
|
||||
want string // "" for an entry that loads
|
||||
}{
|
||||
{
|
||||
"setuid as Unix writes it",
|
||||
0o4755,
|
||||
`file entry has a mode above 0777: "x" (04755)`,
|
||||
},
|
||||
{
|
||||
"setuid as Go keeps it",
|
||||
uint32(os.ModeSetuid | 0o755),
|
||||
`file entry has a mode above 0777: "x" (040000755)`,
|
||||
},
|
||||
{"permission bits only", 0o777, ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
id := uuid.NewV4()
|
||||
inner, err := proto.Marshal(&MFFile{
|
||||
Version: MFFile_VERSION_ONE,
|
||||
Files: []*MFFilePath{{
|
||||
Path: "x",
|
||||
Size: 1,
|
||||
Hashes: []*MFFileChecksum{{MultiHash: hash}},
|
||||
Mode: tt.mode,
|
||||
}},
|
||||
Uuid: id[:],
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
m, err := NewManifestFromReader(bytes.NewReader(wrapInner(t, id, inner)))
|
||||
if tt.want == "" {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, m.Files(), 1)
|
||||
assert.Equal(t, tt.mode, m.Files()[0].GetMode())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
require.ErrorIs(t, err, errModeOutOfRange)
|
||||
require.EqualError(t, err, tt.want)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Entries of a path, a SHA-256 hash, an empty MIME type and empty
|
||||
// modification and change times are counted at 432 bytes each (176 + 112 +
|
||||
// 16 + 64 + 64) and take 52 bytes plus the path to encode. A one-character
|
||||
|
||||
Reference in New Issue
Block a user