about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--tvix/store/protos/castore.go23
-rw-r--r--tvix/store/protos/castore_test.go46
2 files changed, 35 insertions, 34 deletions
diff --git a/tvix/store/protos/castore.go b/tvix/store/protos/castore.go
index 634aa7924f64..4ab7ab42887a 100644
--- a/tvix/store/protos/castore.go
+++ b/tvix/store/protos/castore.go
@@ -1,9 +1,9 @@
 package storev1
 
 import (
+	"bytes"
+	"encoding/base64"
 	"fmt"
-	"strings"
-
 	"google.golang.org/protobuf/proto"
 	"lukechampine.com/blake3"
 )
@@ -43,8 +43,8 @@ func (d *Directory) Digest() ([]byte, error) {
 // We disallow slashes, null bytes, '.', '..' and the empty string.
 // Depending on the context, a *Node message with an empty string as name is
 // allowed, but they don't occur inside a Directory message.
-func isValidName(n string) bool {
-	if n == "" || n == ".." || n == "." || strings.Contains(n, "\x00") || strings.Contains(n, "/") {
+func isValidName(n []byte) bool {
+	if len(n) == 0 || bytes.Equal(n, []byte("..")) || bytes.Equal(n, []byte{'.'}) || bytes.Contains(n, []byte{'\x00'}) || bytes.Contains(n, []byte{'/'}) {
 		return false
 	}
 	return true
@@ -62,14 +62,14 @@ func (d *Directory) Validate() error {
 
 	// We also track the last seen name in each of the three lists,
 	// to ensure nodes are sorted by their names.
-	var lastDirectoryName, lastFileName, lastSymlinkName string
+	var lastDirectoryName, lastFileName, lastSymlinkName []byte
 
 	// helper function to only insert in sorted order.
 	// used with the three lists above.
 	// Note this consumes a *pointer to* a string,  as it mutates it.
-	insertIfGt := func(lastName *string, name string) error {
+	insertIfGt := func(lastName *[]byte, name []byte) error {
 		// update if it's greater than the previous name
-		if name > *lastName {
+		if bytes.Compare(name, *lastName) == 1 {
 			*lastName = name
 			return nil
 		} else {
@@ -78,11 +78,12 @@ func (d *Directory) Validate() error {
 	}
 
 	// insertOnce inserts into seenNames if the key doesn't exist yet.
-	insertOnce := func(name string) error {
-		if _, found := seenNames[name]; found {
-			return fmt.Errorf("duplicate name: %v", name)
+	insertOnce := func(name []byte) error {
+		encoded := base64.StdEncoding.EncodeToString(name)
+		if _, found := seenNames[encoded]; found {
+			return fmt.Errorf("duplicate name: %v", string(name))
 		}
-		seenNames[name] = nil
+		seenNames[encoded] = nil
 		return nil
 	}
 
diff --git a/tvix/store/protos/castore_test.go b/tvix/store/protos/castore_test.go
index 61fe535366d0..15a2554bbb57 100644
--- a/tvix/store/protos/castore_test.go
+++ b/tvix/store/protos/castore_test.go
@@ -29,7 +29,7 @@ func TestDirectorySize(t *testing.T) {
 	t.Run("containing single empty directory", func(t *testing.T) {
 		d := storev1pb.Directory{
 			Directories: []*storev1pb.DirectoryNode{{
-				Name:   "foo",
+				Name:   []byte([]byte("foo")),
 				Digest: dummyDigest,
 				Size:   0,
 			}},
@@ -43,7 +43,7 @@ func TestDirectorySize(t *testing.T) {
 	t.Run("containing single non-empty directory", func(t *testing.T) {
 		d := storev1pb.Directory{
 			Directories: []*storev1pb.DirectoryNode{{
-				Name:   "foo",
+				Name:   []byte("foo"),
 				Digest: dummyDigest,
 				Size:   4,
 			}},
@@ -58,7 +58,7 @@ func TestDirectorySize(t *testing.T) {
 		d := storev1pb.Directory{
 			Directories: []*storev1pb.DirectoryNode{},
 			Files: []*storev1pb.FileNode{{
-				Name:       "foo",
+				Name:       []byte("foo"),
 				Digest:     dummyDigest,
 				Size:       42,
 				Executable: false,
@@ -74,8 +74,8 @@ func TestDirectorySize(t *testing.T) {
 			Directories: []*storev1pb.DirectoryNode{},
 			Files:       []*storev1pb.FileNode{},
 			Symlinks: []*storev1pb.SymlinkNode{{
-				Name:   "foo",
-				Target: "bar",
+				Name:   []byte("foo"),
+				Target: []byte("bar"),
 			}},
 		}
 
@@ -114,7 +114,7 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   "",
+					Name:   []byte{},
 					Digest: dummyDigest,
 					Size:   42,
 				}},
@@ -127,7 +127,7 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   ".",
+					Name:   []byte("."),
 					Digest: dummyDigest,
 					Size:   42,
 				}},
@@ -141,7 +141,7 @@ func TestDirectoryValidate(t *testing.T) {
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{},
 				Files: []*storev1pb.FileNode{{
-					Name:       "..",
+					Name:       []byte(".."),
 					Digest:     dummyDigest,
 					Size:       42,
 					Executable: false,
@@ -156,8 +156,8 @@ func TestDirectoryValidate(t *testing.T) {
 				Directories: []*storev1pb.DirectoryNode{},
 				Files:       []*storev1pb.FileNode{},
 				Symlinks: []*storev1pb.SymlinkNode{{
-					Name:   "\x00",
-					Target: "foo",
+					Name:   []byte("\x00"),
+					Target: []byte("foo"),
 				}},
 			}
 
@@ -168,8 +168,8 @@ func TestDirectoryValidate(t *testing.T) {
 				Directories: []*storev1pb.DirectoryNode{},
 				Files:       []*storev1pb.FileNode{},
 				Symlinks: []*storev1pb.SymlinkNode{{
-					Name:   "foo/bar",
-					Target: "foo",
+					Name:   []byte("foo/bar"),
+					Target: []byte("foo"),
 				}},
 			}
 
@@ -180,7 +180,7 @@ func TestDirectoryValidate(t *testing.T) {
 	t.Run("invalid digest", func(t *testing.T) {
 		d := storev1pb.Directory{
 			Directories: []*storev1pb.DirectoryNode{{
-				Name:   "foo",
+				Name:   []byte("foo"),
 				Digest: nil,
 				Size:   42,
 			}},
@@ -196,11 +196,11 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   "b",
+					Name:   []byte("b"),
 					Digest: dummyDigest,
 					Size:   42,
 				}, {
-					Name:   "a",
+					Name:   []byte("a"),
 					Digest: dummyDigest,
 					Size:   42,
 				}},
@@ -214,12 +214,12 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   "a",
+					Name:   []byte("a"),
 					Digest: dummyDigest,
 					Size:   42,
 				}},
 				Files: []*storev1pb.FileNode{{
-					Name:       "a",
+					Name:       []byte("a"),
 					Digest:     dummyDigest,
 					Size:       42,
 					Executable: false,
@@ -233,11 +233,11 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   "a",
+					Name:   []byte("a"),
 					Digest: dummyDigest,
 					Size:   42,
 				}, {
-					Name:   "b",
+					Name:   []byte("b"),
 					Digest: dummyDigest,
 					Size:   42,
 				}},
@@ -251,18 +251,18 @@ func TestDirectoryValidate(t *testing.T) {
 		{
 			d := storev1pb.Directory{
 				Directories: []*storev1pb.DirectoryNode{{
-					Name:   "b",
+					Name:   []byte("b"),
 					Digest: dummyDigest,
 					Size:   42,
 				}, {
-					Name:   "c",
+					Name:   []byte("c"),
 					Digest: dummyDigest,
 					Size:   42,
 				}},
 				Files: []*storev1pb.FileNode{},
 				Symlinks: []*storev1pb.SymlinkNode{{
-					Name:   "a",
-					Target: "foo",
+					Name:   []byte("a"),
+					Target: []byte("foo"),
 				}},
 			}
 			assert.NoError(t, d.Validate(), "shouldn't error")