mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-18 21:11:19 +02:00
Fail with error when double-rendering text in markdownify/RenderString
This commit prevents the most commons case of infinite recursion in link render hooks when the `linkify` option is enabled (see below). This is always a user error, but getting a `stack overflow` (the current stack limit in Go is 1 GB on 64-bit, 250 MB on 32-bit) error isn't very helpful. This fix will not prevent all such errors, though, but we may do better once #9570 is in place. So, these will fail: ``` <a href="{{ .Destination | safeURL }}" >{{ .Text | markdownify }}</a> <a href="{{ .Destination | safeURL }}" >{{ .Text | .Page.RenderString }}</a> ``` `.Text` is already rendered to `HTML`. The above needs to be rewritten to: ``` <a href="{{ .Destination | safeURL }}" >{{ .Text | safeHTML }}</a> <a href="{{ .Destination | safeURL }}" >{{ .Text | safeHTML }}</a> ``` Fixes #8959
This commit is contained in:
committed by
GitHub
parent
5697348e17
commit
4e14cf7607
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/gohugoio/hugo/common/hugio"
|
||||
"github.com/gohugoio/hugo/common/text"
|
||||
"github.com/gohugoio/hugo/common/types/hstring"
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
"github.com/gohugoio/hugo/markup/internal/attributes"
|
||||
)
|
||||
@@ -32,7 +33,7 @@ type LinkContext interface {
|
||||
Page() interface{}
|
||||
Destination() string
|
||||
Title() string
|
||||
Text() string
|
||||
Text() hstring.RenderedString
|
||||
PlainText() string
|
||||
}
|
||||
|
||||
@@ -75,7 +76,7 @@ type HeadingContext interface {
|
||||
// Anchor is the HTML id assigned to the heading.
|
||||
Anchor() string
|
||||
// Text is the rendered (HTML) heading text, excluding the heading marker.
|
||||
Text() string
|
||||
Text() hstring.RenderedString
|
||||
// PlainText is the unrendered version of Text.
|
||||
PlainText() string
|
||||
|
||||
|
@@ -18,6 +18,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
)
|
||||
|
||||
@@ -395,6 +397,49 @@ FENCE
|
||||
}
|
||||
}
|
||||
|
||||
// Iisse #8959
|
||||
func TestHookInfiniteRecursion(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, renderFunc := range []string{"markdownify", ".Page.RenderString"} {
|
||||
t.Run(renderFunc, func(t *testing.T) {
|
||||
|
||||
files := `
|
||||
-- config.toml --
|
||||
-- layouts/_default/_markup/render-link.html --
|
||||
<a href="{{ .Destination | safeURL }}">{{ .Text | RENDERFUNC }}</a>
|
||||
-- layouts/_default/single.html --
|
||||
{{ .Content }}
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: "p1"
|
||||
---
|
||||
|
||||
https://example.org
|
||||
|
||||
a@b.com
|
||||
|
||||
|
||||
`
|
||||
|
||||
files = strings.ReplaceAll(files, "RENDERFUNC", renderFunc)
|
||||
|
||||
b, err := hugolib.NewIntegrationTestBuilder(
|
||||
hugolib.IntegrationTestConfig{
|
||||
T: t,
|
||||
TxtarString: files,
|
||||
},
|
||||
).BuildE()
|
||||
|
||||
b.Assert(err, qt.IsNotNil)
|
||||
b.Assert(err.Error(), qt.Contains, "text is already rendered, repeating it may cause infinite recursion")
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Issue 9594
|
||||
func TestQuotesInImgAltAttr(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/types/hstring"
|
||||
"github.com/gohugoio/hugo/markup/converter/hooks"
|
||||
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
||||
"github.com/gohugoio/hugo/markup/goldmark/internal/render"
|
||||
@@ -49,7 +50,7 @@ type linkContext struct {
|
||||
page interface{}
|
||||
destination string
|
||||
title string
|
||||
text string
|
||||
text hstring.RenderedString
|
||||
plainText string
|
||||
}
|
||||
|
||||
@@ -65,7 +66,7 @@ func (ctx linkContext) Page() interface{} {
|
||||
return ctx.page
|
||||
}
|
||||
|
||||
func (ctx linkContext) Text() string {
|
||||
func (ctx linkContext) Text() hstring.RenderedString {
|
||||
return ctx.text
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ type headingContext struct {
|
||||
page interface{}
|
||||
level int
|
||||
anchor string
|
||||
text string
|
||||
text hstring.RenderedString
|
||||
plainText string
|
||||
*attributes.AttributesHolder
|
||||
}
|
||||
@@ -98,7 +99,7 @@ func (ctx headingContext) Anchor() string {
|
||||
return ctx.anchor
|
||||
}
|
||||
|
||||
func (ctx headingContext) Text() string {
|
||||
func (ctx headingContext) Text() hstring.RenderedString {
|
||||
return ctx.text
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
|
||||
page: ctx.DocumentContext().Document,
|
||||
destination: string(n.Destination),
|
||||
title: string(n.Title),
|
||||
text: string(text),
|
||||
text: hstring.RenderedString(text),
|
||||
plainText: string(n.Text(source)),
|
||||
},
|
||||
)
|
||||
@@ -226,7 +227,7 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
|
||||
page: ctx.DocumentContext().Document,
|
||||
destination: string(n.Destination),
|
||||
title: string(n.Title),
|
||||
text: string(text),
|
||||
text: hstring.RenderedString(text),
|
||||
plainText: string(n.Text(source)),
|
||||
},
|
||||
)
|
||||
@@ -293,7 +294,7 @@ func (r *hookedRenderer) renderAutoLink(w util.BufWriter, source []byte, node as
|
||||
linkContext{
|
||||
page: ctx.DocumentContext().Document,
|
||||
destination: url,
|
||||
text: label,
|
||||
text: hstring.RenderedString(label),
|
||||
plainText: label,
|
||||
},
|
||||
)
|
||||
@@ -381,7 +382,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast
|
||||
page: ctx.DocumentContext().Document,
|
||||
level: n.Level,
|
||||
anchor: string(anchor),
|
||||
text: string(text),
|
||||
text: hstring.RenderedString(text),
|
||||
plainText: string(n.Text(source)),
|
||||
AttributesHolder: attributes.New(n.Attributes(), attributes.AttributesOwnerGeneral),
|
||||
},
|
||||
|
Reference in New Issue
Block a user