From 29289d466ab817054145324e7c3bbc9e5e4f44b6 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Tue, 19 Jan 2021 19:18:24 +0000 Subject: [PATCH 1/4] Prevent panic on fuzzer provided string The fuzzer has found that providing a tag with an attribute to PostProcess causes a panic. This PR removes any rendered html or body tags from the output. Signed-off-by: Andrew Thornton --- modules/markup/html.go | 35 +++++++++++++++++++++++++++++------ modules/markup/html_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index 9e4b1a3d5d31..dcbaf3b3d268 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -317,8 +317,8 @@ func RenderEmoji( return ctx.postProcess(rawHTML) } -var byteBodyTag = []byte("") -var byteBodyTagClosing = []byte("") +const byteBodyTag = "" +const byteBodyTagClosing = "" func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { if ctx.procs == nil { @@ -327,9 +327,9 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { // give a generous extra 50 bytes res := make([]byte, 0, len(rawHTML)+50) - res = append(res, byteBodyTag...) + res = append(res, ""...) res = append(res, rawHTML...) - res = append(res, byteBodyTagClosing...) + res = append(res, ""...) // parse the HTML nodes, err := html.ParseFragment(bytes.NewReader(res), nil) @@ -341,6 +341,31 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { ctx.visitNode(node, true) } + newNodes := make([]*html.Node, 0, len(nodes)) + + for _, node := range nodes { + if node.Data == "html" { + node = node.FirstChild + for node != nil && node.Data != "body" { + node = node.NextSibling + } + } + if node == nil { + continue + } + if node.Data == "body" { + child := node.FirstChild + for child != nil { + newNodes = append(newNodes, child) + child = child.NextSibling + } + } else { + newNodes = append(newNodes, node) + } + } + + nodes = newNodes + // Create buffer in which the data will be placed again. We know that the // length will be at least that of res; to spare a few alloc+copy, we // reuse res, resetting its length to 0. @@ -353,9 +378,7 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { } } - // remove initial parts - because Render creates a whole HTML page. res = buf.Bytes() - res = res[bytes.Index(res, byteBodyTag)+len(byteBodyTag) : bytes.LastIndex(res, byteBodyTagClosing)] // Everything done successfully, return parsed data. return res, nil diff --git a/modules/markup/html_test.go b/modules/markup/html_test.go index b04781489a83..a78b936f87f1 100644 --- a/modules/markup/html_test.go +++ b/modules/markup/html_test.go @@ -383,3 +383,28 @@ func TestRender_ShortLinks(t *testing.T) { `

[[foobar]]

`, `

[[foobar]]

`) } + +func Test_ParseClusterFuzz(t *testing.T) { + setting.AppURL = AppURL + setting.AppSubURL = AppSubURL + + var localMetas = map[string]string{ + "user": "go-gitea", + "repo": "gitea", + } + + data := "
Date: Wed, 20 Jan 2021 00:13:59 +0000 Subject: [PATCH 2/4] Placate lint --- modules/markup/html.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index dcbaf3b3d268..4c4a06f27e1c 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -317,8 +317,6 @@ func RenderEmoji( return ctx.postProcess(rawHTML) } -const byteBodyTag = "" -const byteBodyTagClosing = "" func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { if ctx.procs == nil { From 3cb8f9ff3ce34a645c25e44355a47cbc0d810a44 Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Wed, 20 Jan 2021 08:52:06 +0000 Subject: [PATCH 3/4] placate lint again Signed-off-by: Andrew Thornton --- modules/markup/html.go | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index 4c4a06f27e1c..d752fe211aed 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -317,7 +317,6 @@ func RenderEmoji( return ctx.postProcess(rawHTML) } - func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { if ctx.procs == nil { ctx.procs = defaultProcessors From bce2a0e42d1538308b9b1fa9232dd9d6429f979b Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Wed, 20 Jan 2021 12:36:04 +0000 Subject: [PATCH 4/4] minor cleanup Signed-off-by: Andrew Thornton --- modules/markup/html.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/markup/html.go b/modules/markup/html.go index d752fe211aed..67aec7371c8d 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -375,10 +375,8 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) { } } - res = buf.Bytes() - // Everything done successfully, return parsed data. - return res, nil + return buf.Bytes(), nil } func (ctx *postProcessCtx) visitNode(node *html.Node, visitText bool) {