Skip to content

Commit d6811ba

Browse files
KN4CK3Ryp05327
andauthored
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>
1 parent c236e64 commit d6811ba

10 files changed

+66
-80
lines changed

modules/git/batch_reader.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -203,16 +203,7 @@ headerLoop:
203203
}
204204

205205
// Discard the rest of the tag
206-
discard := size - n + 1
207-
for discard > math.MaxInt32 {
208-
_, err := rd.Discard(math.MaxInt32)
209-
if err != nil {
210-
return id, err
211-
}
212-
discard -= math.MaxInt32
213-
}
214-
_, err := rd.Discard(int(discard))
215-
return id, err
206+
return id, DiscardFull(rd, size-n+1)
216207
}
217208

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

240231
// Discard the rest of the commit
241-
discard := size - n + 1
242-
for discard > math.MaxInt32 {
243-
_, err := rd.Discard(math.MaxInt32)
244-
if err != nil {
245-
return id, err
246-
}
247-
discard -= math.MaxInt32
248-
}
249-
_, err := rd.Discard(int(discard))
250-
return id, err
232+
return id, DiscardFull(rd, size-n+1)
251233
}
252234

253235
// git tree files are a list:
@@ -345,3 +327,21 @@ func init() {
345327
_, filename, _, _ := runtime.Caller(0)
346328
callerPrefix = strings.TrimSuffix(filename, "modules/git/batch_reader.go")
347329
}
330+
331+
func DiscardFull(rd *bufio.Reader, discard int64) error {
332+
if discard > math.MaxInt32 {
333+
n, err := rd.Discard(math.MaxInt32)
334+
discard -= int64(n)
335+
if err != nil {
336+
return err
337+
}
338+
}
339+
for discard > 0 {
340+
n, err := rd.Discard(int(discard))
341+
discard -= int64(n)
342+
if err != nil {
343+
return err
344+
}
345+
}
346+
return nil
347+
}

modules/git/blob_nogogit.go

+2-22
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"bufio"
1010
"bytes"
1111
"io"
12-
"math"
1312

1413
"code.gitea.io/gitea/modules/log"
1514
)
@@ -104,25 +103,6 @@ func (b *blobReader) Read(p []byte) (n int, err error) {
104103
// Close implements io.Closer
105104
func (b *blobReader) Close() error {
106105
defer b.cancel()
107-
if b.n > 0 {
108-
for b.n > math.MaxInt32 {
109-
n, err := b.rd.Discard(math.MaxInt32)
110-
b.n -= int64(n)
111-
if err != nil {
112-
return err
113-
}
114-
b.n -= math.MaxInt32
115-
}
116-
n, err := b.rd.Discard(int(b.n))
117-
b.n -= int64(n)
118-
if err != nil {
119-
return err
120-
}
121-
}
122-
if b.n == 0 {
123-
_, err := b.rd.Discard(1)
124-
b.n--
125-
return err
126-
}
127-
return nil
106+
107+
return DiscardFull(b.rd, b.n+1)
128108
}

modules/git/commit_info_nogogit.go

+3
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ func GetLastCommitForPaths(ctx context.Context, commit *Commit, treePath string,
151151
return nil, err
152152
}
153153
if typ != "commit" {
154+
if err := DiscardFull(batchReader, size+1); err != nil {
155+
return nil, err
156+
}
154157
return nil, fmt.Errorf("unexpected type: %s for commit id: %s", typ, commitID)
155158
}
156159
c, err = CommitFromReader(commit.repo, MustIDFromString(commitID), io.LimitReader(batchReader, size))

modules/git/pipeline/lfs_nogogit.go

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err
169169
} else {
170170
break commitReadingLoop
171171
}
172+
default:
173+
if err := git.DiscardFull(batchReader, size+1); err != nil {
174+
return nil, err
175+
}
172176
}
173177
}
174178
}

modules/git/repo_commit_nogogit.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ func (repo *Repository) getCommitFromBatchReader(rd *bufio.Reader, id ObjectID)
121121
return commit, nil
122122
default:
123123
log.Debug("Unknown typ: %s", typ)
124-
_, err = rd.Discard(int(size) + 1)
125-
if err != nil {
124+
if err := DiscardFull(rd, size+1); err != nil {
126125
return nil, err
127126
}
128127
return nil, ErrNotExist{

modules/git/repo_language_stats_nogogit.go

+1-22
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
package git
77

88
import (
9-
"bufio"
109
"bytes"
1110
"io"
12-
"math"
1311
"strings"
1412

1513
"code.gitea.io/gitea/modules/analyze"
@@ -168,8 +166,7 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
168166
return nil, err
169167
}
170168
content = contentBuf.Bytes()
171-
err = discardFull(batchReader, discard)
172-
if err != nil {
169+
if err := DiscardFull(batchReader, discard); err != nil {
173170
return nil, err
174171
}
175172
}
@@ -212,21 +209,3 @@ func (repo *Repository) GetLanguageStats(commitID string) (map[string]int64, err
212209

213210
return mergeLanguageStats(sizes), nil
214211
}
215-
216-
func discardFull(rd *bufio.Reader, discard int64) error {
217-
if discard > math.MaxInt32 {
218-
n, err := rd.Discard(math.MaxInt32)
219-
discard -= int64(n)
220-
if err != nil {
221-
return err
222-
}
223-
}
224-
for discard > 0 {
225-
n, err := rd.Discard(int(discard))
226-
discard -= int64(n)
227-
if err != nil {
228-
return err
229-
}
230-
}
231-
return nil
232-
}

modules/git/repo_tag_nogogit.go

+3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
103103
return nil, err
104104
}
105105
if typ != "tag" {
106+
if err := DiscardFull(rd, size+1); err != nil {
107+
return nil, err
108+
}
106109
return nil, ErrNotExist{ID: tagID.String()}
107110
}
108111

modules/git/repo_tree_nogogit.go

+3
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ func (repo *Repository) getTree(id ObjectID) (*Tree, error) {
5858
tree.entriesParsed = true
5959
return tree, nil
6060
default:
61+
if err := DiscardFull(rd, size+1); err != nil {
62+
return nil, err
63+
}
6164
return nil, ErrNotExist{
6265
ID: id.String(),
6366
}

modules/git/tree_nogogit.go

+2-14
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ package git
77

88
import (
99
"io"
10-
"math"
1110
"strings"
1211
)
1312

@@ -63,19 +62,8 @@ func (t *Tree) ListEntries() (Entries, error) {
6362
}
6463

6564
// Not a tree just use ls-tree instead
66-
for sz > math.MaxInt32 {
67-
discarded, err := rd.Discard(math.MaxInt32)
68-
sz -= int64(discarded)
69-
if err != nil {
70-
return nil, err
71-
}
72-
}
73-
for sz > 0 {
74-
discarded, err := rd.Discard(int(sz))
75-
sz -= int64(discarded)
76-
if err != nil {
77-
return nil, err
78-
}
65+
if err := DiscardFull(rd, sz+1); err != nil {
66+
return nil, err
7967
}
8068
}
8169

modules/git/tree_test.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"path/filepath"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestSubTree_Issue29101(t *testing.T) {
14+
repo, err := openRepositoryWithDefaultContext(filepath.Join(testReposDir, "repo1_bare"))
15+
assert.NoError(t, err)
16+
defer repo.Close()
17+
18+
commit, err := repo.GetCommit("ce064814f4a0d337b333e646ece456cd39fab612")
19+
assert.NoError(t, err)
20+
21+
// old code could produce a different error if called multiple times
22+
for i := 0; i < 10; i++ {
23+
_, err = commit.SubTree("file1.txt")
24+
assert.Error(t, err)
25+
assert.True(t, IsErrNotExist(err))
26+
}
27+
}

0 commit comments

Comments
 (0)