diff --git a/_test/extra.txt b/_test/extra.txt index a1e2c9a..f8d89e6 100644 --- a/_test/extra.txt +++ b/_test/extra.txt @@ -392,8 +392,11 @@ a* b c d *e* OPTIONS: {"enableEscape": true} //- - - - - - - - -// hello\x00world + +hello\ufffdworld

+\n") @@ -305,7 +305,7 @@ func (r *Renderer) renderHTMLBlock(w util.BufWriter, source []byte, node ast.Nod if n.HasClosure() { if r.Unsafe { closure := n.ClosureLine - _, _ = w.Write(closure.Value(source)) + r.Writer.SecureWrite(w, closure.Value(source)) } else { _, _ = w.WriteString("\n") } @@ -668,8 +668,13 @@ type Writer interface { // RawWrite writes the given source to writer without resolving references and // unescaping backslash escaped characters. RawWrite(writer util.BufWriter, source []byte) + + // SecureWrite writes the given source to writer with replacing insecure characters. + SecureWrite(writer util.BufWriter, source []byte) } +var replacementCharacter = []byte("\ufffd") + type defaultWriter struct { } @@ -684,6 +689,23 @@ func escapeRune(writer util.BufWriter, r rune) { _, _ = writer.WriteRune(util.ToValidRune(r)) } +func (d *defaultWriter) SecureWrite(writer util.BufWriter, source []byte) { + n := 0 + l := len(source) + for i := 0; i < l; i++ { + if source[i] == '\u0000' { + _, _ = writer.Write(source[i-n : i]) + n = 0 + _, _ = writer.Write(replacementCharacter) + continue + } + n++ + } + if n != 0 { + _, _ = writer.Write(source[l-n:]) + } +} + func (d *defaultWriter) RawWrite(writer util.BufWriter, source []byte) { n := 0 l := len(source) @@ -719,7 +741,7 @@ func (d *defaultWriter) Write(writer util.BufWriter, source []byte) { } if c == '\x00' { d.RawWrite(writer, source[n:i]) - d.RawWrite(writer, []byte("\ufffd")) + d.RawWrite(writer, replacementCharacter) n = i + 1 continue }