From efd63ec1d8c6df180f2d894fa82c53da9d1874f1 Mon Sep 17 00:00:00 2001
From: Gusted <postmaster@gusted.xyz>
Date: Sun, 21 Jul 2024 01:02:31 +0200
Subject: [PATCH] [BUG] Don't panic on empty blockquote

- On a empty blockquote the callout feature would panic, as it expects
to always have at least one child.
- This panic cannot result in a DoS, because any panic that happens
while rendering any markdown input will be recovered gracefully.
- Adds a simple condition to avoid this panic.
---
 modules/markup/markdown/callout/github.go        |  4 ++++
 modules/markup/markdown/callout/github_legacy.go |  4 ++++
 modules/markup/markdown/markdown_test.go         | 14 ++++++++++++++
 3 files changed, 22 insertions(+)

diff --git a/modules/markup/markdown/callout/github.go b/modules/markup/markdown/callout/github.go
index 443f6fe2a3..debad42b83 100644
--- a/modules/markup/markdown/callout/github.go
+++ b/modules/markup/markdown/callout/github.go
@@ -36,6 +36,10 @@ func (g *GitHubCalloutTransformer) Transform(node *ast.Document, reader text.Rea
 
 		switch v := n.(type) {
 		case *ast.Blockquote:
+			if v.ChildCount() == 0 {
+				return ast.WalkContinue, nil
+			}
+
 			// We only want attention blockquotes when the AST looks like:
 			// Text: "["
 			// Text: "!TYPE"
diff --git a/modules/markup/markdown/callout/github_legacy.go b/modules/markup/markdown/callout/github_legacy.go
index e9aaecccfb..eb15e1e64c 100644
--- a/modules/markup/markdown/callout/github_legacy.go
+++ b/modules/markup/markdown/callout/github_legacy.go
@@ -25,6 +25,10 @@ func (g *GitHubLegacyCalloutTransformer) Transform(node *ast.Document, reader te
 
 		switch v := n.(type) {
 		case *ast.Blockquote:
+			if v.ChildCount() == 0 {
+				return ast.WalkContinue, nil
+			}
+
 			// The first paragraph contains the callout type.
 			firstParagraph := v.FirstChild()
 			if firstParagraph.ChildCount() < 1 {
diff --git a/modules/markup/markdown/markdown_test.go b/modules/markup/markdown/markdown_test.go
index d1299bb191..d0bb129b71 100644
--- a/modules/markup/markdown/markdown_test.go
+++ b/modules/markup/markdown/markdown_test.go
@@ -1342,3 +1342,17 @@ key: value
 </tbody>
 </table>`)
 }
+
+func TestCallout(t *testing.T) {
+	setting.AppURL = AppURL
+
+	test := func(input, expected string) {
+		buffer, err := markdown.RenderString(&markup.RenderContext{
+			Ctx: git.DefaultContext,
+		}, input)
+		assert.NoError(t, err)
+		assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(string(buffer)))
+	}
+
+	test(">\n0", "<blockquote>\n</blockquote>\n<p>0</p>")
+}