Skip to content

Commit 45ca2e4

Browse files
Handle incomplete diff files properly (#13662)
* Handle incomplete diff files properly The code for parsing diff hunks has a bug whereby a very long line in a very long diff would not be completely read leading to an unexpected character. This PR ensures that the line is completely cleared Fix #13602 Signed-off-by: Andrew Thornton <[email protected]> * Also allow git max line length <4096 Signed-off-by: Andrew Thornton <[email protected]> * Add test case Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: techknowlogick <[email protected]>
1 parent b651409 commit 45ca2e4

File tree

2 files changed

+96
-6
lines changed

2 files changed

+96
-6
lines changed

services/gitdiff/gitdiff.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,15 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
676676
leftLine, rightLine := 1, 1
677677

678678
for {
679+
for isFragment {
680+
curFile.IsIncomplete = true
681+
_, isFragment, err = input.ReadLine()
682+
if err != nil {
683+
// Now by the definition of ReadLine this cannot be io.EOF
684+
err = fmt.Errorf("Unable to ReadLine: %v", err)
685+
return
686+
}
687+
}
679688
sb.Reset()
680689
lineBytes, isFragment, err = input.ReadLine()
681690
if err != nil {
@@ -790,6 +799,10 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
790799
}
791800
}
792801
}
802+
if len(line) > maxLineCharacters {
803+
curFile.IsIncomplete = true
804+
line = line[:maxLineCharacters]
805+
}
793806
curSection.Lines[len(curSection.Lines)-1].Content = line
794807

795808
// handle LFS

services/gitdiff/gitdiff_test.go

Lines changed: 83 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"encoding/json"
1010
"fmt"
1111
"html/template"
12+
"strconv"
1213
"strings"
1314
"testing"
1415

@@ -153,11 +154,11 @@ func TestParsePatch_singlefile(t *testing.T) {
153154
name: "really weird filename",
154155
gitdiff: `diff --git "\\a/a b/file b/a a/file" "\\b/a b/file b/a a/file"
155156
index d2186f1..f5c8ed2 100644
156-
--- "\\a/a b/file b/a a/file"
157-
+++ "\\b/a b/file b/a a/file"
157+
--- "\\a/a b/file b/a a/file" ` + `
158+
+++ "\\b/a b/file b/a a/file" ` + `
158159
@@ -1,3 +1,2 @@
159160
Create a weird file.
160-
161+
` + `
161162
-and what does diff do here?
162163
\ No newline at end of file`,
163164
addition: 0,
@@ -170,7 +171,7 @@ index d2186f1..f5c8ed2 100644
170171
gitdiff: `diff --git "\\a/file with blanks" "\\b/file with blanks"
171172
deleted file mode 100644
172173
index 898651a..0000000
173-
--- "\\a/file with blanks"
174+
--- "\\a/file with blanks" ` + `
174175
+++ /dev/null
175176
@@ -1,5 +0,0 @@
176177
-a blank file
@@ -263,7 +264,83 @@ index 6961180..9ba1a00 100644
263264
})
264265
}
265266

266-
var diff = `diff --git "a/README.md" "b/README.md"
267+
// Test max lines
268+
diffBuilder := &strings.Builder{}
269+
270+
var diff = `diff --git a/newfile2 b/newfile2
271+
new file mode 100644
272+
index 0000000..6bb8f39
273+
--- /dev/null
274+
+++ b/newfile2
275+
@@ -0,0 +1,35 @@
276+
`
277+
diffBuilder.WriteString(diff)
278+
279+
for i := 0; i < 35; i++ {
280+
diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n")
281+
}
282+
diff = diffBuilder.String()
283+
result, err := ParsePatch(20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
284+
if err != nil {
285+
t.Errorf("There should not be an error: %v", err)
286+
}
287+
if !result.Files[0].IsIncomplete {
288+
t.Errorf("Files should be incomplete! %v", result.Files[0])
289+
}
290+
result, err = ParsePatch(40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
291+
if err != nil {
292+
t.Errorf("There should not be an error: %v", err)
293+
}
294+
if result.Files[0].IsIncomplete {
295+
t.Errorf("Files should not be incomplete! %v", result.Files[0])
296+
}
297+
result, err = ParsePatch(40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
298+
if err != nil {
299+
t.Errorf("There should not be an error: %v", err)
300+
}
301+
if !result.Files[0].IsIncomplete {
302+
t.Errorf("Files should be incomplete! %v", result.Files[0])
303+
}
304+
305+
// Test max characters
306+
diff = `diff --git a/newfile2 b/newfile2
307+
new file mode 100644
308+
index 0000000..6bb8f39
309+
--- /dev/null
310+
+++ b/newfile2
311+
@@ -0,0 +1,35 @@
312+
`
313+
diffBuilder.Reset()
314+
diffBuilder.WriteString(diff)
315+
316+
for i := 0; i < 33; i++ {
317+
diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n")
318+
}
319+
diffBuilder.WriteString("+line33")
320+
for i := 0; i < 512; i++ {
321+
diffBuilder.WriteString("0123456789ABCDEF")
322+
}
323+
diffBuilder.WriteByte('\n')
324+
diffBuilder.WriteString("+line" + strconv.Itoa(34) + "\n")
325+
diffBuilder.WriteString("+line" + strconv.Itoa(35) + "\n")
326+
diff = diffBuilder.String()
327+
328+
result, err = ParsePatch(20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
329+
if err != nil {
330+
t.Errorf("There should not be an error: %v", err)
331+
}
332+
if !result.Files[0].IsIncomplete {
333+
t.Errorf("Files should be incomplete! %v", result.Files[0])
334+
}
335+
result, err = ParsePatch(40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
336+
if err != nil {
337+
t.Errorf("There should not be an error: %v", err)
338+
}
339+
if !result.Files[0].IsIncomplete {
340+
t.Errorf("Files should be incomplete! %v", result.Files[0])
341+
}
342+
343+
diff = `diff --git "a/README.md" "b/README.md"
267344
--- a/README.md
268345
+++ b/README.md
269346
@@ -1,3 +1,6 @@
@@ -274,7 +351,7 @@ index 6961180..9ba1a00 100644
274351
Docker Pulls
275352
+ cut off
276353
+ cut off`
277-
result, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
354+
result, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff))
278355
if err != nil {
279356
t.Errorf("ParsePatch failed: %s", err)
280357
}

0 commit comments

Comments
 (0)