@ -35,13 +35,8 @@ var urlPrefixKey = parser.NewContextKey()
var isWikiKey = parser . NewContextKey ( )
var isWikiKey = parser . NewContextKey ( )
var renderMetasKey = parser . NewContextKey ( )
var renderMetasKey = parser . NewContextKey ( )
type closesWithError interface {
io . WriteCloser
CloseWithError ( err error ) error
}
type limitWriter struct {
type limitWriter struct {
w closesWithErro r
w io . Writer
sum int64
sum int64
limit int64
limit int64
}
}
@ -55,7 +50,6 @@ func (l *limitWriter) Write(data []byte) (int, error) {
if err != nil {
if err != nil {
return n , err
return n , err
}
}
_ = l . w . Close ( )
return n , fmt . Errorf ( "Rendered content too large - truncating render" )
return n , fmt . Errorf ( "Rendered content too large - truncating render" )
}
}
n , err := l . w . Write ( data )
n , err := l . w . Write ( data )
@ -63,16 +57,6 @@ func (l *limitWriter) Write(data []byte) (int, error) {
return n , err
return n , err
}
}
// Close closes the writer
func ( l * limitWriter ) Close ( ) error {
return l . w . Close ( )
}
// CloseWithError closes the writer
func ( l * limitWriter ) CloseWithError ( err error ) error {
return l . w . CloseWithError ( err )
}
// newParserContext creates a parser.Context with the render context set
// newParserContext creates a parser.Context with the render context set
func newParserContext ( ctx * markup . RenderContext ) parser . Context {
func newParserContext ( ctx * markup . RenderContext ) parser . Context {
pc := parser . NewContext ( parser . WithIDs ( newPrefixedIDs ( ) ) )
pc := parser . NewContext ( parser . WithIDs ( newPrefixedIDs ( ) ) )
@ -153,51 +137,40 @@ func actualRender(ctx *markup.RenderContext, input io.Reader, output io.Writer)
} )
} )
rd , wr := io . Pipe ( )
defer func ( ) {
_ = rd . Close ( )
_ = wr . Close ( )
} ( )
lw := & limitWriter {
lw := & limitWriter {
w : wr ,
w : output ,
limit : setting . UI . MaxDisplayFileSize * 3 ,
limit : setting . UI . MaxDisplayFileSize * 3 ,
}
}
// FIXME: should we include a timeout that closes the pipe to abort the renderer and sanitizer if it takes too long?
// FIXME: should we include a timeout to abort the renderer if it takes too long?
go func ( ) {
defer func ( ) {
defer func ( ) {
err := recover ( )
err := recover ( )
if err == nil {
if err == nil {
return
}
log . Warn ( "Unable to render markdown due to panic in goldmark: %v" , err )
if log . IsDebug ( ) {
log . Debug ( "Panic in markdown: %v\n%s" , err , string ( log . Stack ( 2 ) ) )
}
_ = lw . CloseWithError ( fmt . Errorf ( "%v" , err ) )
} ( )
// 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
return
}
}
if err := converter . Convert ( giteautil . NormalizeEOL ( buf ) , lw , parser . WithContext ( pc ) ) ; err != nil {
log . Error ( "Unable to render: %v" , err )
log . Warn ( "Unable to render markdown due to panic in goldmark: %v" , err )
_ = lw . CloseWithError ( err )
if log . IsDebug ( ) {
return
log . Debug ( "Panic in markdown: %v\n%s" , err , string ( log . Stack ( 2 ) ) )
}
}
_ = lw . Close ( )
} ( )
} ( )
buf := markup . SanitizeReader ( rd , "" )
_ , err := io . Copy ( output , buf )
// FIXME: Don't read all to memory, but goldmark doesn't support
return err
pc := newParserContext ( ctx )
buf , err := io . ReadAll ( input )
if err != nil {
log . Error ( "Unable to ReadAll: %v" , err )
return err
}
if err := converter . Convert ( giteautil . NormalizeEOL ( buf ) , lw , parser . WithContext ( pc ) ) ; err != nil {
log . Error ( "Unable to render: %v" , err )
return err
}
return nil
}
}
// Note: The output of this method must get sanitized.
func render ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
func render ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
defer func ( ) {
defer func ( ) {
err := recover ( )
err := recover ( )
@ -205,14 +178,13 @@ func render(ctx *markup.RenderContext, input io.Reader, output io.Writer) error
return
return
}
}
log . Warn ( "Unable to render markdown due to panic in goldmark - will return sanitized raw bytes" )
log . Warn ( "Unable to render markdown due to panic in goldmark - will return raw bytes" )
if log . IsDebug ( ) {
if log . IsDebug ( ) {
log . Debug ( "Panic in markdown: %v\n%s" , err , string ( log . Stack ( 2 ) ) )
log . Debug ( "Panic in markdown: %v\n%s" , err , string ( log . Stack ( 2 ) ) )
}
}
ret := markup . SanitizeReader ( input , "" )
_ , err = io . Copy ( output , input )
_ , err = io . Copy ( output , ret )
if err != nil {
if err != nil {
log . Error ( "SanitizeReader failed: %v" , err )
log . Error ( "io.Copy failed: %v" , err )
}
}
} ( )
} ( )
return actualRender ( ctx , input , output )
return actualRender ( ctx , input , output )
@ -255,8 +227,8 @@ func (Renderer) Render(ctx *markup.RenderContext, input io.Reader, output io.Wri
// Render renders Markdown to HTML with all specific handling stuff.
// Render renders Markdown to HTML with all specific handling stuff.
func Render ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
func Render ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
if ctx . Filenam e == "" {
if ctx . Typ e == "" {
ctx . Filename = "a.md"
ctx . Type = MarkupName
}
}
return markup . Render ( ctx , input , output )
return markup . Render ( ctx , input , output )
}
}
@ -272,7 +244,21 @@ func RenderString(ctx *markup.RenderContext, content string) (string, error) {
// RenderRaw renders Markdown to HTML without handling special links.
// RenderRaw renders Markdown to HTML without handling special links.
func RenderRaw ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
func RenderRaw ( ctx * markup . RenderContext , input io . Reader , output io . Writer ) error {
return render ( ctx , input , output )
rd , wr := io . Pipe ( )
defer func ( ) {
_ = rd . Close ( )
_ = wr . Close ( )
} ( )
go func ( ) {
if err := render ( ctx , input , wr ) ; err != nil {
_ = wr . CloseWithError ( err )
return
}
_ = wr . Close ( )
} ( )
return markup . SanitizeReader ( rd , "" , output )
}
}
// RenderRawString renders Markdown to HTML without handling special links and return string
// RenderRawString renders Markdown to HTML without handling special links and return string