Skip to content

Commit 1709297

Browse files
authored
Fix SHA1 hash linking (#2143) (#2293)
This changes the regex to look for a hash from 7 to 40 characters, to match the use of abbreviated hash lookups in both git and github. The restriction of not being a pure number is also removed because 1234567 is now considered a valid abbreviated hash, as is deadbeef. A note has been added to the top of the code to state that the literal regex match is fine, but no extra validation is currently performed so some false positives are expected. A future change could ensure that the hash exists in the repository before rendering it as a link, although this might incur a slight performance penalty. Reverts part of commit 4a46613 and fixes #2053.
1 parent 5fe8fee commit 1709297

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

modules/markdown/markdown.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ func IsReadmeFile(name string) bool {
5353
}
5454

5555
var (
56+
// NOTE: All below regex matching do not perform any extra validation.
57+
// Thus a link is produced even if the user does not exist, the issue does not exist, the commit does not exist, etc.
58+
// While fast, this is also incorrect and lead to false positives.
59+
5660
// MentionPattern matches string that mentions someone, e.g. @Unknwon
5761
MentionPattern = regexp.MustCompile(`(\s|^|\W)@[0-9a-zA-Z-_\.]+`)
5862

@@ -65,9 +69,9 @@ var (
6569
CrossReferenceIssueNumericPattern = regexp.MustCompile(`( |^)[0-9a-zA-Z]+/[0-9a-zA-Z]+#[0-9]+\b`)
6670

6771
// Sha1CurrentPattern matches string that represents a commit SHA, e.g. d8a994ef243349f321568f9e36d5c3f444b99cae
68-
// FIXME: this pattern matches pure numbers as well, right now we do a hack to check in renderSha1CurrentPattern
69-
// by converting string to a number.
70-
Sha1CurrentPattern = regexp.MustCompile(`(?:^|\s|\()[0-9a-f]{40}\b`)
72+
// Although SHA1 hashes are 40 chars long, the regex matches the hash from 7 to 40 chars in length
73+
// so that abbreviated hash links can be used as well. This matches git and github useability.
74+
Sha1CurrentPattern = regexp.MustCompile(`(?:^|\s|\()([0-9a-f]{7,40})\b`)
7175

7276
// ShortLinkPattern matches short but difficult to parse [[name|link|arg=test]] syntax
7377
ShortLinkPattern = regexp.MustCompile(`(\[\[.*\]\]\w*)`)
@@ -553,12 +557,15 @@ func RenderCrossReferenceIssueIndexPattern(rawBytes []byte, urlPrefix string, me
553557
func renderSha1CurrentPattern(rawBytes []byte, urlPrefix string) []byte {
554558
ms := Sha1CurrentPattern.FindAllSubmatch(rawBytes, -1)
555559
for _, m := range ms {
556-
all := m[0]
557-
if com.StrTo(all).MustInt() > 0 {
558-
continue
559-
}
560-
rawBytes = bytes.Replace(rawBytes, all, []byte(fmt.Sprintf(
561-
`<a href="%s">%s</a>`, URLJoin(urlPrefix, "commit", string(all)), base.ShortSha(string(all)))), -1)
560+
hash := m[1]
561+
// The regex does not lie, it matches the hash pattern.
562+
// However, a regex cannot know if a hash actually exists or not.
563+
// We could assume that a SHA1 hash should probably contain alphas AND numerics
564+
// but that is not always the case.
565+
// Although unlikely, deadbeef and 1234567 are valid short forms of SHA1 hash
566+
// as used by git and github for linking and thus we have to do similar.
567+
rawBytes = bytes.Replace(rawBytes, hash, []byte(fmt.Sprintf(
568+
`<a href="%s">%s</a>`, URLJoin(urlPrefix, "commit", string(hash)), base.ShortSha(string(hash)))), -1)
562569
}
563570
return rawBytes
564571
}

modules/markdown/markdown_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ func TestRender_Commits(t *testing.T) {
290290
var src = strings.Replace(subtree, "/commit/", "/src/", -1)
291291

292292
test(sha, `<p><a href="`+commit+`" rel="nofollow">b6dd6210ea</a></p>`)
293+
test(sha[:7], `<p><a href="`+commit[:len(commit)-(40-7)]+`" rel="nofollow">b6dd621</a></p>`)
294+
test(sha[:39], `<p><a href="`+commit[:len(commit)-(40-39)]+`" rel="nofollow">b6dd6210ea</a></p>`)
293295
test(commit, `<p><a href="`+commit+`" rel="nofollow">b6dd6210ea</a></p>`)
294296
test(tree, `<p><a href="`+src+`" rel="nofollow">b6dd6210ea/src</a></p>`)
295297
}

0 commit comments

Comments
 (0)