1package snapshot
2
3import (
4 "errors"
5 "os"
6 "path/filepath"
7 "syscall"
8 "testing"
9
10 codec "github.com/bnema/vev/internal/usecase/snapshot"
11)
12
13func TestReadBoundedRejectsUnsafeFiles(t *testing.T) {
14 dir := t.TempDir()
15 regular := filepath.Join(dir, "regular")
16 if err := os.WriteFile(regular, []byte("safe"), 0o600); err != nil {
17 t.Fatal(err)
18 }
19 tooLarge := filepath.Join(dir, "large")
20 f, err := os.Create(tooLarge)
21 if err != nil {
22 t.Fatal(err)
23 }
24 if err := f.Truncate(maxRepositoryRead + 1); err != nil {
25 t.Fatal(err)
26 }
27 if err := f.Close(); err != nil {
28 t.Fatal(err)
29 }
30 unsafeMode := filepath.Join(dir, "mode")
31 if err := os.WriteFile(unsafeMode, []byte("unsafe"), 0o644); err != nil {
32 t.Fatal(err)
33 }
34 link := filepath.Join(dir, "link")
35 if err := os.Symlink(regular, link); err != nil {
36 t.Fatal(err)
37 }
38 fifo := filepath.Join(dir, "fifo")
39 if err := syscall.Mkfifo(fifo, 0o600); err != nil {
40 t.Fatal(err)
41 }
42
43 for _, path := range []string{tooLarge, unsafeMode, link, fifo} {
44 t.Run(filepath.Base(path), func(t *testing.T) {
45 if _, err := readBounded(path); err == nil {
46 t.Fatal("readBounded accepted unsafe file")
47 }
48 })
49 }
50
51 wrongOwner := filepath.Join(dir, "owner")
52 if os.Geteuid() == 0 {
53 if err := os.WriteFile(wrongOwner, []byte("unsafe"), 0o600); err != nil {
54 t.Fatal(err)
55 }
56 if err := os.Chown(wrongOwner, 1, -1); err != nil {
57 t.Fatal(err)
58 }
59 if _, err := readBounded(wrongOwner); err == nil {
60 t.Fatal("readBounded accepted wrong-owner file")
61 }
62 }
63}
64
65func TestValidatePublicationRejectsUnloadableAggregate(t *testing.T) {
66 pub := repositoryPublication(t, "named", 1, []byte("state"))
67 manifest, err := codec.UnmarshalManifest(pub.Manifest)
68 if err != nil {
69 t.Fatal(err)
70 }
71 manifest.Tabs[0].Panes[0].Tail.Size = uint32(maxRepositoryRead)
72 manifest.Tabs[0].Panes[0].Transcript.Size = uint32(maxRepositoryRead)
73 pub.Manifest, err = codec.MarshalManifest(manifest)
74 if err != nil {
75 t.Fatal(err)
76 }
77 pub.Objects = nil // validation permits omitted objects for immutable reuse.
78 if _, _, err := validatePublication(pub); err == nil {
79 t.Fatal("validatePublication accepted unloadable aggregate")
80 } else if errors.Is(err, os.ErrNotExist) {
81 t.Fatalf("validatePublication returned unrelated error: %v", err)
82 }
83}