forked from gitea/gitea
Discard unread data of `git cat-file` (#29297)
Fixes #29101 Related #29298 Discard all read data to prevent misinterpreting existing data. Some discard calls were missing in error cases. --------- Co-authored-by: yp05327 <576951401@qq.com>
This commit is contained in:
parent
c236e64aca
commit
d6811baf88
|
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -169,6 +169,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
|
|||
} else {
|
||||
break commitReadingLoop
|
||||
}
|
||||
default:
|
||||
if err := git.DiscardFull(batchReader, size+1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,8 +121,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
|
|||
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{
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"io"
|
||||
"math"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -103,6 +103,9 @@ func (repo *Repository) getTag(tagID ObjectID, 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()}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ func (repo *Repository) getTree(id ObjectID) (*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(),
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ package git
|
|||
|
||||
import (
|
||||
"io"
|
||||
"math"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue