Skip to content

Commit fb274ec

Browse files
6543zeripath
andauthored
Prevent panic on fuzzer provided string (#14405) (#14409)
* Prevent panic on fuzzer provided string The fuzzer has found that providing a <body> 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 <[email protected]> * Placate lint * placate lint again Signed-off-by: Andrew Thornton <[email protected]> * minor cleanup Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: zeripath <[email protected]>
1 parent 0c3f950 commit fb274ec

File tree

2 files changed

+53
-10
lines changed

2 files changed

+53
-10
lines changed

modules/markup/html.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,19 +298,16 @@ func RenderEmoji(
298298
return ctx.postProcess(rawHTML)
299299
}
300300

301-
var byteBodyTag = []byte("<body>")
302-
var byteBodyTagClosing = []byte("</body>")
303-
304301
func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
305302
if ctx.procs == nil {
306303
ctx.procs = defaultProcessors
307304
}
308305

309306
// give a generous extra 50 bytes
310307
res := make([]byte, 0, len(rawHTML)+50)
311-
res = append(res, byteBodyTag...)
308+
res = append(res, "<html><body>"...)
312309
res = append(res, rawHTML...)
313-
res = append(res, byteBodyTagClosing...)
310+
res = append(res, "</body></html>"...)
314311

315312
// parse the HTML
316313
nodes, err := html.ParseFragment(bytes.NewReader(res), nil)
@@ -322,6 +319,31 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
322319
ctx.visitNode(node, true)
323320
}
324321

322+
newNodes := make([]*html.Node, 0, len(nodes))
323+
324+
for _, node := range nodes {
325+
if node.Data == "html" {
326+
node = node.FirstChild
327+
for node != nil && node.Data != "body" {
328+
node = node.NextSibling
329+
}
330+
}
331+
if node == nil {
332+
continue
333+
}
334+
if node.Data == "body" {
335+
child := node.FirstChild
336+
for child != nil {
337+
newNodes = append(newNodes, child)
338+
child = child.NextSibling
339+
}
340+
} else {
341+
newNodes = append(newNodes, node)
342+
}
343+
}
344+
345+
nodes = newNodes
346+
325347
// Create buffer in which the data will be placed again. We know that the
326348
// length will be at least that of res; to spare a few alloc+copy, we
327349
// reuse res, resetting its length to 0.
@@ -334,12 +356,8 @@ func (ctx *postProcessCtx) postProcess(rawHTML []byte) ([]byte, error) {
334356
}
335357
}
336358

337-
// remove initial parts - because Render creates a whole HTML page.
338-
res = buf.Bytes()
339-
res = res[bytes.Index(res, byteBodyTag)+len(byteBodyTag) : bytes.LastIndex(res, byteBodyTagClosing)]
340-
341359
// Everything done successfully, return parsed data.
342-
return res, nil
360+
return buf.Bytes(), nil
343361
}
344362

345363
func (ctx *postProcessCtx) visitNode(node *html.Node, visitText bool) {

modules/markup/html_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,28 @@ func TestRender_ShortLinks(t *testing.T) {
383383
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`,
384384
`<p><a href="https://example.org" rel="nofollow">[[foobar]]</a></p>`)
385385
}
386+
387+
func Test_ParseClusterFuzz(t *testing.T) {
388+
setting.AppURL = AppURL
389+
setting.AppSubURL = AppSubURL
390+
391+
var localMetas = map[string]string{
392+
"user": "go-gitea",
393+
"repo": "gitea",
394+
}
395+
396+
data := "<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
397+
398+
val, err := PostProcess([]byte(data), "https://example.com", localMetas, false)
399+
400+
assert.NoError(t, err)
401+
assert.NotContains(t, string(val), "<html")
402+
403+
data = "<!DOCTYPE html>\n<A><maTH><tr><MN><bodY ÿ><temPlate></template><tH><tr></A><tH><d<bodY "
404+
405+
val, err = PostProcess([]byte(data), "https://example.com", localMetas, false)
406+
407+
assert.NoError(t, err)
408+
409+
assert.NotContains(t, string(val), "<html")
410+
}

0 commit comments

Comments
 (0)