mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
Fix bugs found in fuzzing
This commit is contained in:
parent
21b4a046d0
commit
a27b0ef209
3 changed files with 109 additions and 32 deletions
|
|
@ -78,9 +78,9 @@ func (b *fencedCodeBlockParser) Continue(node ast.Node, reader text.Reader, pc C
|
||||||
return Close
|
return Close
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pos, padding := util.DedentPositionPadding(line, reader.LineOffset(), segment.Padding, fdata.indent)
|
||||||
|
|
||||||
pos, padding := util.DedentPosition(line, fdata.indent)
|
seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding)
|
||||||
seg := text.NewSegmentPadding(segment.Start+pos-segment.Padding, segment.Stop, padding)
|
|
||||||
node.Lines().Append(seg)
|
node.Lines().Append(seg)
|
||||||
reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
|
reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
|
||||||
return Continue | NoChildren
|
return Continue | NoChildren
|
||||||
|
|
|
||||||
35
testutil.go
35
testutil.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/yuin/goldmark/util"
|
"github.com/yuin/goldmark/util"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
testing "testing"
|
testing "testing"
|
||||||
|
|
@ -78,11 +79,31 @@ func DoTestCaseFile(m Markdown, filename string, t *testing.T) {
|
||||||
|
|
||||||
func DoTestCases(m Markdown, cases []MarkdownTestCase, t *testing.T) {
|
func DoTestCases(m Markdown, cases []MarkdownTestCase, t *testing.T) {
|
||||||
for _, testCase := range cases {
|
for _, testCase := range cases {
|
||||||
var out bytes.Buffer
|
DoTestCase(m, testCase, t)
|
||||||
if err := m.Convert([]byte(testCase.Markdown), &out); err != nil {
|
}
|
||||||
panic(err)
|
}
|
||||||
}
|
|
||||||
if !bytes.Equal(bytes.TrimSpace(out.Bytes()), bytes.TrimSpace([]byte(testCase.Expected))) {
|
func DoTestCase(m Markdown, testCase MarkdownTestCase, t *testing.T) {
|
||||||
|
var ok bool
|
||||||
|
var out bytes.Buffer
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
format := `============= case %d ================
|
||||||
|
Markdown:
|
||||||
|
-----------
|
||||||
|
%s
|
||||||
|
|
||||||
|
Expected:
|
||||||
|
----------
|
||||||
|
%s
|
||||||
|
|
||||||
|
Actual
|
||||||
|
---------
|
||||||
|
%v
|
||||||
|
%s
|
||||||
|
`
|
||||||
|
t.Errorf(format, testCase.No, testCase.Markdown, testCase.Expected, err, debug.Stack())
|
||||||
|
} else if !ok {
|
||||||
format := `============= case %d ================
|
format := `============= case %d ================
|
||||||
Markdown:
|
Markdown:
|
||||||
-----------
|
-----------
|
||||||
|
|
@ -98,6 +119,10 @@ Actual
|
||||||
`
|
`
|
||||||
t.Errorf(format, testCase.No, testCase.Markdown, testCase.Expected, out.Bytes())
|
t.Errorf(format, testCase.No, testCase.Markdown, testCase.Expected, out.Bytes())
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := m.Convert([]byte(testCase.Markdown), &out); err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
ok = bytes.Equal(bytes.TrimSpace(out.Bytes()), bytes.TrimSpace([]byte(testCase.Expected)))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
102
util/util.go
102
util/util.go
|
|
@ -87,31 +87,6 @@ func IsBlank(bs []byte) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// DedentPosition dedents lines by the given width.
|
|
||||||
func DedentPosition(bs []byte, width int) (pos, padding int) {
|
|
||||||
if width == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
i := 0
|
|
||||||
l := len(bs)
|
|
||||||
w := 0
|
|
||||||
for ; i < l && w < width; i++ {
|
|
||||||
b := bs[i]
|
|
||||||
if b == ' ' {
|
|
||||||
w++
|
|
||||||
} else if b == '\t' {
|
|
||||||
w += 4
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
padding = w - width
|
|
||||||
if padding < 0 {
|
|
||||||
padding = 0
|
|
||||||
}
|
|
||||||
return i, padding
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisualizeSpaces visualize invisible space characters.
|
// VisualizeSpaces visualize invisible space characters.
|
||||||
func VisualizeSpaces(bs []byte) []byte {
|
func VisualizeSpaces(bs []byte) []byte {
|
||||||
bs = bytes.Replace(bs, []byte(" "), []byte("[SPACE]"), -1)
|
bs = bytes.Replace(bs, []byte(" "), []byte("[SPACE]"), -1)
|
||||||
|
|
@ -137,6 +112,9 @@ func TabWidth(currentPos int) int {
|
||||||
// width=2 is in the tab character. In this case, IndentPosition returns
|
// width=2 is in the tab character. In this case, IndentPosition returns
|
||||||
// (pos=1, padding=2)
|
// (pos=1, padding=2)
|
||||||
func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
||||||
|
if width == 0 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
w := 0
|
w := 0
|
||||||
l := len(bs)
|
l := len(bs)
|
||||||
i := 0
|
i := 0
|
||||||
|
|
@ -160,6 +138,80 @@ func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
||||||
return -1, -1
|
return -1, -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IndentPositionPadding searches an indent position with the given width for the given line.
|
||||||
|
// This function is mostly same as IndentPosition except this function
|
||||||
|
// takes account into additional paddings.
|
||||||
|
func IndentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
|
||||||
|
if width == 0 {
|
||||||
|
return 0, paddingv
|
||||||
|
}
|
||||||
|
w := 0
|
||||||
|
i := 0
|
||||||
|
l := len(bs)
|
||||||
|
for ; i < l; i++ {
|
||||||
|
if bs[i] == '\t' {
|
||||||
|
w += TabWidth(currentPos + w)
|
||||||
|
} else if bs[i] == ' ' {
|
||||||
|
w++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w >= width {
|
||||||
|
return i - paddingv, w - width
|
||||||
|
}
|
||||||
|
return -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DedentPosition dedents lines by the given width.
|
||||||
|
func DedentPosition(bs []byte, currentPos, width int) (pos, padding int) {
|
||||||
|
if width == 0 {
|
||||||
|
return 0, 0
|
||||||
|
}
|
||||||
|
w := 0
|
||||||
|
l := len(bs)
|
||||||
|
i := 0
|
||||||
|
for ; i < l; i++ {
|
||||||
|
if bs[i] == '\t' {
|
||||||
|
w += TabWidth(currentPos + w)
|
||||||
|
} else if bs[i] == ' ' {
|
||||||
|
w++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w >= width {
|
||||||
|
return i, w - width
|
||||||
|
}
|
||||||
|
return i, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DedentPositionPadding dedents lines by the given width.
|
||||||
|
// This function is mostly same as DedentPosition except this function
|
||||||
|
// takes account into additional paddings.
|
||||||
|
func DedentPositionPadding(bs []byte, currentPos, paddingv, width int) (pos, padding int) {
|
||||||
|
if width == 0 {
|
||||||
|
return 0, paddingv
|
||||||
|
}
|
||||||
|
|
||||||
|
w := 0
|
||||||
|
i := 0
|
||||||
|
l := len(bs)
|
||||||
|
for ; i < l; i++ {
|
||||||
|
if bs[i] == '\t' {
|
||||||
|
w += TabWidth(currentPos + w)
|
||||||
|
} else if bs[i] == ' ' {
|
||||||
|
w++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w >= width {
|
||||||
|
return i - paddingv, w - width
|
||||||
|
}
|
||||||
|
return i - paddingv, 0
|
||||||
|
}
|
||||||
|
|
||||||
// IndentWidth calculate an indent width for the given line.
|
// IndentWidth calculate an indent width for the given line.
|
||||||
func IndentWidth(bs []byte, currentPos int) (width, pos int) {
|
func IndentWidth(bs []byte, currentPos int) (width, pos int) {
|
||||||
l := len(bs)
|
l := len(bs)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue