Skip to content

Commit d61ea8d

Browse files
committed
Fix index out of bounds panic when repository has massive tag lists
1 parent 26f2c02 commit d61ea8d

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

pkg/commands/git_commands/commit_loader.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,17 +202,33 @@ func (self *CommitLoader) MergeRebasingCommits(hashPool *utils.StringPool, commi
202202
func (self *CommitLoader) extractCommitFromLine(hashPool *utils.StringPool, line string, showDivergence bool) *models.Commit {
203203
split := strings.SplitN(line, "\x00", 8)
204204

205+
// Ensure we have the minimum required fields (at least 5 for basic functionality)
206+
if len(split) < 5 {
207+
self.Log.Warnf("Malformed git log line: expected at least 5 fields, got %d. Line: %s", len(split), line)
208+
return nil
209+
}
210+
205211
hash := split[0]
206212
unixTimestamp := split[1]
207213
authorName := split[2]
208214
authorEmail := split[3]
209215
extraInfo := strings.TrimSpace(split[4])
210-
parentHashes := split[5]
216+
217+
// Safe access to optional fields with defaults
218+
parentHashes := ""
219+
if len(split) > 5 {
220+
parentHashes = split[5]
221+
}
222+
211223
divergence := models.DivergenceNone
212-
if showDivergence {
224+
if showDivergence && len(split) > 6 {
213225
divergence = lo.Ternary(split[6] == "<", models.DivergenceLeft, models.DivergenceRight)
214226
}
215-
message := split[7]
227+
228+
message := ""
229+
if len(split) > 7 {
230+
message = split[7]
231+
}
216232

217233
tags := []string{}
218234

pkg/commands/git_commands/commit_loader_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,3 +588,61 @@ func TestCommitLoader_setCommitMergedStatuses(t *testing.T) {
588588
})
589589
}
590590
}
591+
592+
func TestCommitLoader_extractCommitFromLine(t *testing.T) {
593+
common := common.NewDummyCommon()
594+
hashPool := &utils.StringPool{}
595+
596+
loader := &CommitLoader{
597+
Common: common,
598+
}
599+
600+
scenarios := []struct {
601+
testName string
602+
line string
603+
showDivergence bool
604+
expectedNil bool
605+
}{
606+
{
607+
testName: "normal commit line",
608+
line: "0eea75e8c631fba6b58135697835d58ba4c18dbc\x001640826609\x00Jesse Duffield\x00jessedduffield@gmail.com\x00HEAD -> better-tests\x00b21997d6b4cbdf84b149\x00>\x00better typing for rebase mode",
609+
showDivergence: true,
610+
expectedNil: false,
611+
},
612+
{
613+
testName: "malformed line with only 3 fields",
614+
line: "hash\x00timestamp\x00author",
615+
showDivergence: false,
616+
expectedNil: true,
617+
},
618+
{
619+
testName: "malformed line with only 4 fields",
620+
line: "hash\x00timestamp\x00author\x00email",
621+
showDivergence: false,
622+
expectedNil: true,
623+
},
624+
{
625+
testName: "minimal valid line with 5 fields",
626+
line: "hash\x00timestamp\x00author\x00email\x00extraInfo",
627+
showDivergence: false,
628+
expectedNil: false,
629+
},
630+
{
631+
testName: "line missing divergence field when expected",
632+
line: "hash\x00timestamp\x00author\x00email\x00extraInfo\x00parents",
633+
showDivergence: true,
634+
expectedNil: false,
635+
},
636+
}
637+
638+
for _, scenario := range scenarios {
639+
t.Run(scenario.testName, func(t *testing.T) {
640+
result := loader.extractCommitFromLine(hashPool, scenario.line, scenario.showDivergence)
641+
if scenario.expectedNil {
642+
assert.Nil(t, result)
643+
} else {
644+
assert.NotNil(t, result)
645+
}
646+
})
647+
}
648+
}

0 commit comments

Comments
 (0)