Skip to content

Commit bd25bd6

Browse files
committed
Fix panic bug in handling multiple references in commit
The issue lay in determining the position of matches on a second run round a commit message in FindAllIssueReferences. Fix go-gitea#13483 Signed-off-by: Andrew Thornton <[email protected]>
1 parent ffa712e commit bd25bd6

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

modules/references/references.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,30 +240,67 @@ func FindAllIssueReferences(content string) []IssueReference {
240240
// Need to convert fully qualified html references to local system to #/! short codes
241241
contentBytes := []byte(content)
242242
if re := getGiteaIssuePullPattern(); re != nil {
243+
// We will iterate through the content, rewrite and simplify full references.
244+
//
245+
// We want to transform something like:
246+
//
247+
// 0 1 2 3 4 5 6
248+
// 012345678901234567890123456789012345678901234567890123456789012345789
249+
// this is a https://ourgitea.com/git/owner/repo/issues/123456789, foo
250+
// https://ourgitea.com/git/owner/repo/pulls/123456789
251+
//
252+
// Into something like:
253+
//
254+
// this is a #123456789, foo
255+
// !123456789
256+
243257
pos := 0
244258
for {
259+
// re looks for something like: (\s|^|\(|\[)https://ourgitea.com/git/(owner/repo)/(issues)/(123456789)(?:\s|$|\)|\]|[:;,.?!]\s|[:;,.?!]$)
245260
match := re.FindSubmatchIndex(contentBytes[pos:])
246261
if match == nil {
247262
break
248263
}
264+
// match is a bunch of indices into the content from pos onwards so if our content is:
265+
266+
// To simplify things let's just add pos to all of the indices in match
267+
for i := range match {
268+
match[i] += pos
269+
}
270+
249271
// match[0]-match[1] is whole string
250272
// match[2]-match[3] is preamble
251-
pos += match[3]
273+
274+
// move the position to the end of the preamble
275+
pos = match[3]
276+
252277
// match[4]-match[5] is owner/repo
278+
// now copy the owner/repo to end of the preamble
253279
endPos := pos + match[5] - match[4]
254280
copy(contentBytes[pos:endPos], contentBytes[match[4]:match[5]])
281+
282+
// move the current position to the end of the newly copied owner/repo
255283
pos = endPos
284+
285+
// Now set the issue/pull marker:
286+
//
256287
// match[6]-match[7] == 'issues'
257288
contentBytes[pos] = '#'
258289
if string(contentBytes[match[6]:match[7]]) == "pulls" {
259290
contentBytes[pos] = '!'
260291
}
261292
pos++
293+
294+
// Then add the issue/pull number
295+
//
262296
// match[8]-match[9] is the number
263297
endPos = pos + match[9] - match[8]
264298
copy(contentBytes[pos:endPos], contentBytes[match[8]:match[9]])
299+
300+
// Now copy what's left at the end of the string to the new end position
265301
copy(contentBytes[endPos:], contentBytes[match[9]:])
266302
// now we reset the length
303+
267304
// our new section has length endPos - match[3]
268305
// our old section has length match[9] - match[3]
269306
contentBytes = contentBytes[:len(contentBytes)-match[9]+endPos]

modules/references/references_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ func TestFindAllIssueReferences(t *testing.T) {
106106
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
107107
},
108108
},
109+
{
110+
"This http://gitea.com:3000/user4/repo5/pulls/202 yes. http://gitea.com:3000/user4/repo5/pulls/203 no",
111+
[]testResult{
112+
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
113+
{203, "user4", "repo5", "203", true, XRefActionNone, nil, nil, ""},
114+
},
115+
},
109116
{
110117
"This http://GiTeA.COM:3000/user4/repo6/pulls/205 yes.",
111118
[]testResult{

0 commit comments

Comments
 (0)