diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go index b5fffccdb9..ace31eb540 100644 --- a/modules/markup/markdown/markdown.go +++ b/modules/markup/markdown/markdown.go @@ -159,6 +159,14 @@ func render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error limit: setting.UI.MaxDisplayFileSize * 3, } + // FIXME: Don't read all to memory, but goldmark doesn't support + buf, err := io.ReadAll(input) + if err != nil { + log.Error("Unable to ReadAll: %v", err) + return err + } + buf = giteautil.NormalizeEOL(buf) + // FIXME: should we include a timeout to abort the renderer if it takes too long? defer func() { err := recover() @@ -166,20 +174,12 @@ func render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error return } - log.Warn("Unable to render markdown due to panic in goldmark: %v", err) - if (!setting.IsProd && !setting.IsInTesting) || log.IsDebug() { - log.Error("Panic in markdown: %v\n%s", err, log.Stack(2)) - } + log.Error("Panic in markdown: %v\n%s", err, log.Stack(2)) + escapedHTML := template.HTMLEscapeString(giteautil.UnsafeBytesToString(buf)) + _, _ = output.Write(giteautil.UnsafeStringToBytes(escapedHTML)) }() - // FIXME: Don't read all to memory, but goldmark doesn't support pc := newParserContext(ctx) - buf, err := io.ReadAll(input) - if err != nil { - log.Error("Unable to ReadAll: %v", err) - return err - } - buf = giteautil.NormalizeEOL(buf) // Preserve original length. bufWithMetadataLength := len(buf) diff --git a/modules/markup/markdown/markdown_attention_test.go b/modules/markup/markdown/markdown_attention_test.go index f6ec775b2c..7b54653ec0 100644 --- a/modules/markup/markdown/markdown_attention_test.go +++ b/modules/markup/markdown/markdown_attention_test.go @@ -23,6 +23,11 @@ func TestAttention(t *testing.T) { defer svg.MockIcon("octicon-alert")() defer svg.MockIcon("octicon-stop")() + test := func(input, expected string) { + result, err := markdown.RenderString(markup.NewTestRenderContext(), input) + assert.NoError(t, err) + assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(result))) + } renderAttention := func(attention, icon string) string { tmpl := `

{Attention}

` tmpl = strings.ReplaceAll(tmpl, "{attention}", attention) @@ -31,12 +36,6 @@ func TestAttention(t *testing.T) { return tmpl } - test := func(input, expected string) { - result, err := markdown.RenderString(markup.NewTestRenderContext(), input) - assert.NoError(t, err) - assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(result))) - } - test(` > [!NOTE] > text @@ -53,4 +52,7 @@ func TestAttention(t *testing.T) { // legacy GitHub style test(`> **warning**`, renderAttention("warning", "octicon-alert")+"\n
") + + // edge case (it used to cause panic) + test(">\ntext", "
\n
\n

text

") } diff --git a/modules/markup/markdown/transform_blockquote.go b/modules/markup/markdown/transform_blockquote.go index 2651d44a69..3a8c6fa018 100644 --- a/modules/markup/markdown/transform_blockquote.go +++ b/modules/markup/markdown/transform_blockquote.go @@ -115,6 +115,9 @@ func (g *ASTTransformer) transformBlockquote(v *ast.Blockquote, reader text.Read // grab these nodes and make sure we adhere to the attention blockquote structure firstParagraph := v.FirstChild() + if firstParagraph == nil { + return ast.WalkContinue, nil + } g.applyElementDir(firstParagraph) attentionType, processedNodes := g.extractBlockquoteAttentionEmphasis(firstParagraph, reader) diff --git a/modules/markup/renderer_test.go b/modules/markup/renderer_test.go deleted file mode 100644 index 0791081f94..0000000000 --- a/modules/markup/renderer_test.go +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package markup_test