Skip to content

Commit

Permalink
Merge pull request #967 from niukuo/filename
Browse files Browse the repository at this point in the history
plumbing: object, check legitimacy in (*Tree).Encode
  • Loading branch information
pjbgf committed Mar 9, 2024
2 parents efdd399 + 1d4bec0 commit d9497ba
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
32 changes: 32 additions & 0 deletions plumbing/object/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"path"
"path/filepath"
"sort"
"strings"

"github.com/go-git/go-git/v5/plumbing"
Expand All @@ -27,6 +28,7 @@ var (
ErrFileNotFound = errors.New("file not found")
ErrDirectoryNotFound = errors.New("directory not found")
ErrEntryNotFound = errors.New("entry not found")
ErrEntriesNotSorted = errors.New("entries in tree are not sorted")
)

// Tree is basically like a directory - it references a bunch of other trees
Expand Down Expand Up @@ -270,6 +272,28 @@ func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
return nil
}

type TreeEntrySorter []TreeEntry

func (s TreeEntrySorter) Len() int {
return len(s)
}

func (s TreeEntrySorter) Less(i, j int) bool {
name1 := s[i].Name
name2 := s[j].Name
if s[i].Mode == filemode.Dir {
name1 += "/"
}
if s[j].Mode == filemode.Dir {
name2 += "/"
}
return name1 < name2
}

func (s TreeEntrySorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}

// Encode transforms a Tree into a plumbing.EncodedObject.
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.TreeObject)
Expand All @@ -279,7 +303,15 @@ func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
}

defer ioutil.CheckClose(w, &err)

if !sort.IsSorted(TreeEntrySorter(t.Entries)) {
return ErrEntriesNotSorted
}

for _, entry := range t.Entries {
if strings.IndexByte(entry.Name, 0) != -1 {
return fmt.Errorf("malformed filename %q", entry.Name)
}
if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
return err
}
Expand Down
26 changes: 26 additions & 0 deletions plumbing/object/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"io"
"sort"
"testing"

fixtures "github.com/go-git/go-git-fixtures/v4"
Expand Down Expand Up @@ -220,6 +221,30 @@ func (o *SortReadCloser) Read(p []byte) (int, error) {
return nw, nil
}

func (s *TreeSuite) TestTreeEntriesSorted(c *C) {
tree := &Tree{
Entries: []TreeEntry{
{"foo", filemode.Empty, plumbing.NewHash("b029517f6300c2da0f4b651b8642506cd6aaf45d")},
{"bar", filemode.Empty, plumbing.NewHash("c029517f6300c2da0f4b651b8642506cd6aaf45d")},
{"baz", filemode.Empty, plumbing.NewHash("d029517f6300c2da0f4b651b8642506cd6aaf45d")},
},
}

{
c.Assert(sort.IsSorted(TreeEntrySorter(tree.Entries)), Equals, false)
obj := &plumbing.MemoryObject{}
err := tree.Encode(obj)
c.Assert(err, Equals, ErrEntriesNotSorted)
}

{
sort.Sort(TreeEntrySorter(tree.Entries))
obj := &plumbing.MemoryObject{}
err := tree.Encode(obj)
c.Assert(err, IsNil)
}
}

func (s *TreeSuite) TestTreeDecodeEncodeIdempotent(c *C) {
trees := []*Tree{
{
Expand All @@ -231,6 +256,7 @@ func (s *TreeSuite) TestTreeDecodeEncodeIdempotent(c *C) {
},
}
for _, tree := range trees {
sort.Sort(TreeEntrySorter(tree.Entries))
obj := &plumbing.MemoryObject{}
err := tree.Encode(obj)
c.Assert(err, IsNil)
Expand Down

0 comments on commit d9497ba

Please sign in to comment.