Skip to content

Commit

Permalink
Discard unread data of git cat-file (#29297) (#29310)
Browse files Browse the repository at this point in the history
Backport #29297 by @KN4CK3R

Fixes #29101
Related #29298

Discard all read data to prevent misinterpreting existing data. Some
discard calls were missing in error cases.

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
Co-authored-by: yp05327 <576951401@qq.com>
  • Loading branch information
3 people authored Feb 22, 2024
1 parent 0870e0b commit ed5e0c8
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 80 deletions.
40 changes: 20 additions & 20 deletions modules/git/batch_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,7 @@ headerLoop:
}

// Discard the rest of the tag
discard := size - n + 1
for discard > math.MaxInt32 {
_, err := rd.Discard(math.MaxInt32)
if err != nil {
return id, err
}
discard -= math.MaxInt32
}
_, err := rd.Discard(int(discard))
return id, err
return id, DiscardFull(rd, size-n+1)
}

// ReadTreeID reads a tree ID from a cat-file --batch stream, throwing away the rest of the stream.
Expand All @@ -238,16 +229,7 @@ headerLoop:
}

// Discard the rest of the commit
discard := size - n + 1
for discard > math.MaxInt32 {
_, err := rd.Discard(math.MaxInt32)
if err != nil {
return id, err
}
discard -= math.MaxInt32
}
_, err := rd.Discard(int(discard))
return id, err
return id, DiscardFull(rd, size-n+1)
}

// git tree files are a list:
Expand Down Expand Up @@ -345,3 +327,21 @@ func init() {
_, filename, _, _ := runtime.Caller(0)
callerPrefix = strings.TrimSuffix(filename, "modules/git/batch_reader.go")
}

func DiscardFull(rd *bufio.Reader, discard int64) error {
if discard > math.MaxInt32 {
n, err := rd.Discard(math.MaxInt32)
discard -= int64(n)
if err != nil {
return err
}
}
for discard > 0 {
n, err := rd.Discard(int(discard))
discard -= int64(n)
if err != nil {
return err
}
}
return nil
}
24 changes: 2 additions & 22 deletions modules/git/blob_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"bufio"
"bytes"
"io"
"math"

"code.gitea.io/gitea/modules/log"
)
Expand Down Expand Up @@ -104,25 +103,6 @@ func (b *blobReader) Read(p []byte) (n int, err error) {
// Close implements io.Closer
func (b *blobReader) Close() error {
defer b.cancel()
if b.n > 0 {
for b.n > math.MaxInt32 {
n, err := b.rd.Discard(math.MaxInt32)
b.n -= int64(n)
if err != nil {
return err
}
b.n -= math.MaxInt32
}
n, err := b.rd.Discard(int(b.n))
b.n -= int64(n)
if err != nil {
return err
}
}
if b.n == 0 {
_, err := b.rd.Discard(1)
b.n--
return err
}
return nil

return DiscardFull(b.rd, b.n+1)
}
3 changes: 3 additions & 0 deletions modules/git/commit_info_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
return nil, err
}
if typ != "commit" {
if err := DiscardFull(batchReader, size+1); err != nil {
return nil, err
}
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
}
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))
Expand Down
4 changes: 4 additions & 0 deletions modules/git/pipeline/lfs_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ func FindLFSFile(repo *git.Repository, hash git.SHA1) ([]*LFSResult, error) {
} else {
break commitReadingLoop
}
default:
if err := git.DiscardFull(batchReader, size+1); err != nil {
return nil, err
}
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions modules/git/repo_commit_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id SHA1) (*Co
return commit, nil
default:
log.Debug("Unknown typ: %s", typ)
_, err = rd.Discard(int(size) + 1)
if err != nil {
if err := DiscardFull(rd, size+1); err != nil {
return nil, err
}
return nil, ErrNotExist{
Expand Down
23 changes: 1 addition & 22 deletions modules/git/repo_language_stats_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
package git

import (
"bufio"
"bytes"
"io"
"math"
"strings"

"code.gitea.io/gitea/modules/analyze"
Expand Down Expand Up @@ -168,8 +166,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
return nil, err
}
content = contentBuf.Bytes()
err = discardFull(batchReader, discard)
if err != nil {
if err := DiscardFull(batchReader, discard); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -212,21 +209,3 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err

return mergeLanguageStats(sizes), nil
}

func discardFull(rd *bufio.Reader, discard int64) error {
if discard > math.MaxInt32 {
n, err := rd.Discard(math.MaxInt32)
discard -= int64(n)
if err != nil {
return err
}
}
for discard > 0 {
n, err := rd.Discard(int(discard))
discard -= int64(n)
if err != nil {
return err
}
}
return nil
}
3 changes: 3 additions & 0 deletions modules/git/repo_tag_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ func (repo *Repository) getTag(tagID SHA1, name string) (*Tag, error) {
return nil, err
}
if typ != "tag" {
if err := DiscardFull(rd, size+1); err != nil {
return nil, err
}
return nil, ErrNotExist{ID: tagID.String()}
}

Expand Down
3 changes: 3 additions & 0 deletions modules/git/repo_tree_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
tree.entriesParsed = true
return tree, nil
default:
if err := DiscardFull(rd, size+1); err != nil {
return nil, err
}
return nil, ErrNotExist{
ID: id.String(),
}
Expand Down
16 changes: 2 additions & 14 deletions modules/git/tree_nogogit.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package git

import (
"io"
"math"
"strings"
)

Expand Down Expand Up @@ -63,19 +62,8 @@ func (t *Tree) ListEntries() (Entries, error) {
}

// Not a tree just use ls-tree instead
for sz > math.MaxInt32 {
discarded, err := rd.Discard(math.MaxInt32)
sz -= int64(discarded)
if err != nil {
return nil, err
}
}
for sz > 0 {
discarded, err := rd.Discard(int(sz))
sz -= int64(discarded)
if err != nil {
return nil, err
}
if err := DiscardFull(rd, sz+1); err != nil {
return nil, err
}
}

Expand Down
27 changes: 27 additions & 0 deletions modules/git/tree_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package git

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSubTree_Issue29101(t *testing.T) {
repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
assert.NoError(t, err)
defer repo.Close()

commit, err := repo.GetCommit("ce064814f4a0d337b333e646ece456cd39fab612")
assert.NoError(t, err)

// old code could produce a different error if called multiple times
for i := 0; i < 10; i++ {
_, err = commit.SubTree("file1.txt")
assert.Error(t, err)
assert.True(t, IsErrNotExist(err))
}
}

0 comments on commit ed5e0c8

Please sign in to comment.