From a3e7fe1f113d0e63ce9a0fd55bfc7757b0a52c08 Mon Sep 17 00:00:00 2001 From: Shudhanshu Singh Date: Fri, 31 Jul 2026 19:19:47 +0530 Subject: [PATCH] fix(gitdiff): prevent index out of range panic in GetLineTypeMarker (#38728) Fixes a `runtime error: index out of range [0] with length 0` panic when executing template `repo/diff/section_unified` because `GetLineTypeMarker()` indexes into empty `DiffLine` content. The regression was introduced in PR #38706 (`94c61137e4`) where `Content: " "` was removed from the initialization of `tailDiffLine`. Guarding `GetLineTypeMarker()` directly makes Gitea defensive and robust against empty diff line values regardless of the source path. Fixes https://github.com/go-gitea/gitea/issues/38724 ### Tests - Added `TestDiffLine_GetLineTypeMarker` covering empty content, prefixes, and normal text formats. Signed-off-by: Sudhanshu Singh --- services/gitdiff/gitdiff.go | 3 +++ services/gitdiff/gitdiff_test.go | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index d1e3027f07..f524afc465 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -170,6 +170,9 @@ func (d *DiffLine) GetCommentSide() string { // GetLineTypeMarker returns the line type marker func (d *DiffLine) GetLineTypeMarker() string { + if d.Content == "" { + return "" + } if strings.IndexByte(" +-", d.Content[0]) > -1 { return d.Content[0:1] } diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index bc61dda1ce..d483ac60a7 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -601,6 +601,16 @@ func TestDiffLine_GetCommentSide(t *testing.T) { assert.Equal(t, "proposed", (&DiffLine{Comments: []*issues_model.Comment{{Line: 3}}}).GetCommentSide()) } +func TestDiffLine_GetLineTypeMarker(t *testing.T) { + assert.Equal(t, "", (&DiffLine{Content: ""}).GetLineTypeMarker()) + assert.Equal(t, "+", (&DiffLine{Content: "+added line"}).GetLineTypeMarker()) + assert.Equal(t, "-", (&DiffLine{Content: "-deleted line"}).GetLineTypeMarker()) + assert.Equal(t, " ", (&DiffLine{Content: " unchanged line"}).GetLineTypeMarker()) + // for a real diff line (including hunk header) from diff output, "Content" should always have a prefix char in [" ", "+", "-"]. + // for other cases, e.g.: a diff line constructed by our code without real diff output, it is undefined behavior at the moment. + assert.Equal(t, "", (&DiffLine{Content: "any-content"}).GetLineTypeMarker()) +} + func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) { gitRepo, err := git.OpenRepositoryLocal(t.Context(), "../../modules/git/tests/repos/repo5_pulls") require.NoError(t, err)