Skip to content

Commit

Permalink
Fix bugs found in fuzzing
Browse files Browse the repository at this point in the history
  • Loading branch information
yuin committed Jul 25, 2019
1 parent 21b4a04 commit a27b0ef
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 32 deletions.
4 changes: 2 additions & 2 deletions parser/fcode_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ func (b *fencedCodeBlockParser) Continue(node ast.Node, reader text.Reader, pc C
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.Padding, segment.Stop, padding)
seg := text.NewSegmentPadding(segment.Start+pos, segment.Stop, padding)
node.Lines().Append(seg)
reader.AdvanceAndSetPadding(segment.Stop-segment.Start-pos-1, padding)
return Continue | NoChildren
Expand Down
35 changes: 30 additions & 5 deletions testutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"github.com/yuin/goldmark/util"
"os"
"runtime/debug"
"strconv"
"strings"
testing "testing"
Expand Down Expand Up @@ -78,11 +79,31 @@ func DoTestCaseFile(m Markdown, filename string, t *testing.T) {

func DoTestCases(m Markdown, cases []MarkdownTestCase, t *testing.T) {
for _, testCase := range cases {
var out bytes.Buffer
if err := m.Convert([]byte(testCase.Markdown), &out); err != nil {
panic(err)
}
if !bytes.Equal(bytes.TrimSpace(out.Bytes()), bytes.TrimSpace([]byte(testCase.Expected))) {
DoTestCase(m, testCase, t)
}
}

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 ================
Markdown:
-----------
Expand All @@ -98,6 +119,10 @@ Actual
`
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 changes: 77 additions & 25 deletions util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,31 +87,6 @@ func IsBlank(bs []byte) bool {
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.
func VisualizeSpaces(bs []byte) []byte {
bs = bytes.Replace(bs, []byte(" "), []byte("[SPACE]"), -1)
Expand All @@ -137,6 +112,9 @@ func TabWidth(currentPos int) int {
// width=2 is in the tab character. In this case, IndentPosition returns
// (pos=1, padding=2)
func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
if width == 0 {
return 0, 0
}
w := 0
l := len(bs)
i := 0
Expand All @@ -160,6 +138,80 @@ func IndentPosition(bs []byte, currentPos, width int) (pos, padding int) {
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.
func IndentWidth(bs []byte, currentPos int) (width, pos int) {
l := len(bs)
Expand Down

0 comments on commit a27b0ef

Please sign in to comment.