From e85dbf37be64e22e2c1f3786539f2e6831085147 Mon Sep 17 00:00:00 2001 From: Vinayak Mishra Date: Tue, 17 Feb 2026 11:48:15 +0545 Subject: [PATCH] fix: skip empty citation segments after semicolon split citation() panics with index-out-of-range when input contains empty segments after splitting on semicolons (e.g. [@;], [@ref;], [@ref1;;@ref2]). bytes.Split produces empty slices for adjacent/trailing semicolons. Add a length check before indexing into the trimmed citation slice. --- parser/citation.go | 3 +++ parser/citation_test.go | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/parser/citation.go b/parser/citation.go index 217d4def..5790e22a 100644 --- a/parser/citation.go +++ b/parser/citation.go @@ -49,6 +49,9 @@ func citation(p *Parser, data []byte, offset int) (int, ast.Node) { for _, citation := range citations { var suffix []byte citation = bytes.TrimSpace(citation) + if len(citation) == 0 { + continue + } j := 0 if citation[j] != '@' { // not a citation, drop out entirely. diff --git a/parser/citation_test.go b/parser/citation_test.go index 635d6f30..b6e0e51b 100644 --- a/parser/citation_test.go +++ b/parser/citation_test.go @@ -43,6 +43,23 @@ func TestCitationSuffix(t *testing.T) { } } +func TestCitationEmptySegment(t *testing.T) { + p := New() + p.extensions |= Mmark + + // These inputs should not panic + inputs := [][]byte{ + []byte(`[@;]`), + []byte(`[@ref;]`), + []byte(`[@ref1;;@ref2]`), + } + for _, data := range inputs { + _, node := citation(p, data, 0) + // empty segments are skipped; result depends on remaining valid citations + _ = node + } +} + func TestCitationSuffixMultiple(t *testing.T) { data := []byte(`[@?RFC1034; @!RFC1035, p. 144, more]`)