Skip to content

Commit 02b5b3f

Browse files
committed
Fix CSV render error (go-gitea#17406)
closed go-gitea#17378 Both errors from go-gitea#17378 were caused by go-gitea#15175. Problem 1 (error with added file): `ToUTF8WithFallbackReader` creates a `MultiReader` from a `byte[2048]` and the remaining reader. `CreateReaderAndGuessDelimiter` tries to read 10000 bytes from this reader but only gets 2048 because that's the first reader in the `MultiReader`. Then the `if size < 1e4` thinks the input is at EOF and just returns that. Problem 2 (error with changed file): The blob reader gets defer closed. That was fine because the old version reads the whole file into memory. Now with the streaming version the close needs to defer after the method.
1 parent 06da10b commit 02b5b3f

File tree

2 files changed

+21
-22
lines changed

2 files changed

+21
-22
lines changed

modules/csv/csv.go

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func CreateReader(input io.Reader, delimiter rune) *stdcsv.Reader {
2828
}
2929

3030
// CreateReaderAndGuessDelimiter tries to guess the field delimiter from the content and creates a csv.Reader.
31+
// Reads at most 10k bytes.
3132
func CreateReaderAndGuessDelimiter(rd io.Reader) (*stdcsv.Reader, error) {
3233
var data = make([]byte, 1e4)
3334
size, err := rd.Read(data)
@@ -38,25 +39,16 @@ func CreateReaderAndGuessDelimiter(rd io.Reader) (*stdcsv.Reader, error) {
3839
return nil, err
3940
}
4041

41-
delimiter := guessDelimiter(data[:size])
42-
43-
var newInput io.Reader
44-
if size < 1e4 {
45-
newInput = bytes.NewReader(data[:size])
46-
} else {
47-
newInput = io.MultiReader(bytes.NewReader(data), rd)
48-
}
49-
50-
return CreateReader(newInput, delimiter), nil
42+
return CreateReader(
43+
io.MultiReader(bytes.NewReader(data[:size]), rd),
44+
guessDelimiter(data[:size]),
45+
), nil
5146
}
5247

5348
// guessDelimiter scores the input CSV data against delimiters, and returns the best match.
54-
// Reads at most 10k bytes & 10 lines.
5549
func guessDelimiter(data []byte) rune {
5650
maxLines := 10
57-
maxBytes := util.Min(len(data), 1e4)
58-
text := string(data[:maxBytes])
59-
text = quoteRegexp.ReplaceAllLiteralString(text, "")
51+
text := quoteRegexp.ReplaceAllLiteralString(string(data), "")
6052
lines := strings.SplitN(text, "\n", maxLines+1)
6153
lines = lines[:util.Min(maxLines, len(lines))]
6254

routers/web/repo/compare.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"errors"
1111
"fmt"
1212
"html"
13+
"io"
1314
"net/http"
1415
"path"
1516
"path/filepath"
@@ -104,30 +105,36 @@ func setCsvCompareContext(ctx *context.Context) {
104105

105106
errTooLarge := errors.New(ctx.Locale.Tr("repo.error.csv.too_large"))
106107

107-
csvReaderFromCommit := func(c *git.Commit) (*csv.Reader, error) {
108+
csvReaderFromCommit := func(c *git.Commit) (*csv.Reader, io.Closer, error) {
108109
blob, err := c.GetBlobByPath(diffFile.Name)
109110
if err != nil {
110-
return nil, err
111+
return nil, nil, err
111112
}
112113

113114
if setting.UI.CSV.MaxFileSize != 0 && setting.UI.CSV.MaxFileSize < blob.Size() {
114-
return nil, errTooLarge
115+
return nil, nil, errTooLarge
115116
}
116117

117118
reader, err := blob.DataAsync()
118119
if err != nil {
119-
return nil, err
120+
return nil, nil, err
120121
}
121-
defer reader.Close()
122122

123-
return csv_module.CreateReaderAndGuessDelimiter(charset.ToUTF8WithFallbackReader(reader))
123+
csvReader, err := csv_module.CreateReaderAndGuessDelimiter(charset.ToUTF8WithFallbackReader(reader))
124+
return csvReader, reader, err
124125
}
125126

126-
baseReader, err := csvReaderFromCommit(baseCommit)
127+
baseReader, baseBlobCloser, err := csvReaderFromCommit(baseCommit)
128+
if baseBlobCloser != nil {
129+
defer baseBlobCloser.Close()
130+
}
127131
if err == errTooLarge {
128132
return CsvDiffResult{nil, err.Error()}
129133
}
130-
headReader, err := csvReaderFromCommit(headCommit)
134+
headReader, headBlobCloser, err := csvReaderFromCommit(headCommit)
135+
if headBlobCloser != nil {
136+
defer headBlobCloser.Close()
137+
}
131138
if err == errTooLarge {
132139
return CsvDiffResult{nil, err.Error()}
133140
}

0 commit comments

Comments
 (0)